k6 gRPC Client Connection Error Fix
In this tutorial, you'll learn about k6 grpc client connection error fix. We cover key concepts, practical examples, and best practices.
Your k6 gRPC client throws rpc error: code = Unavailable desc = connection closed — the gRPC server is unreachable, TLS is misconfigured, or the protobuf definition is not loaded correctly for the k6/net/grpc module.
The Problem
import grpc from 'k6/net/grpc';
const client = new grpc.Client();
export default function () {
client.connect('localhost:50051');
const response = client.invoke('users.UserService/GetUser', { id: 1 });
console.log(response);
}
ERRO[0001] rpc error: code = Unavailable desc = connection closed
at invoke (4)
The gRPC server is not running on localhost:50051, TLS is required but not configured, or the protobuf service definition is missing.
Step-by-Step Fix
1. Load protobuf definitions
import grpc from 'k6/net/grpc';
import { check } from 'k6';
const client = new grpc.Client();
client.load(['./protos'], 'user_service.proto');
export default function () {
client.connect('localhost:50051', { plaintext: true });
const response = client.invoke('users.UserService/GetUser', { id: 1 });
check(response, {
'status is OK': (r) => r.status === grpc.StatusOK,
});
console.log(`User: ${response.message.name}`);
client.close();
}
2. Configure TLS
import grpc from 'k6/net/grpc';
const client = new grpc.Client();
client.load(['./protos'], 'user_service.proto');
export default function () {
// Without TLS (development)
client.connect('localhost:50051', { plaintext: true });
// With TLS (production)
client.connect('api.example.com:443', {
plaintext: false,
tls: {
domains: ['api.example.com'],
},
});
const response = client.invoke('users.UserService/GetUser', { id: 1 });
client.close();
}
3. Handle gRPC errors
import grpc from 'k6/net/grpc';
import { check } from 'k6';
const client = new grpc.Client();
client.load(['./protos'], 'user_service.proto');
export default function () {
client.connect('localhost:50051', { plaintext: true });
try {
const response = client.invoke('users.UserService/GetUser', { id: 1 }, {
timeout: '5s',
});
check(response, {
'status is OK': (r) => r.status === grpc.StatusOK,
});
if (response.status !== grpc.StatusOK) {
console.log(`gRPC error: ${response.error}`);
}
} catch (e) {
console.log(`Exception: ${e}`);
} finally {
client.close();
}
}
4. Use gRPC streaming
import grpc from 'k6/net/grpc';
import { check } from 'k6';
const client = new grpc.Client();
client.load(['./protos'], 'user_service.proto');
export default function () {
client.connect('localhost:50051', { plaintext: true });
const stream = client.invoke('users.UserService/ListUsers', {
page_size: 10,
}, {
timeout: '10s',
});
stream.on('data', function (data) {
console.log(`User: ${data.name}`);
});
stream.on('end', function () {
console.log('Stream ended');
});
client.close();
}
5. Set gRPC options and metadata
import grpc from 'k6/net/grpc';
const client = new grpc.Client();
client.load(['./protos'], 'user_service.proto');
export default function () {
client.connect('localhost:50051', {
plaintext: true,
maxReceiveSize: 10 * 1024 * 1024, // 10 MB
});
const response = client.invoke('users.UserService/GetUser', { id: 1 }, {
metadata: {
'authorization': `Bearer ${__ENV.TOKEN}`,
'x-request-id': `test-${__VU}-${__ITER}`,
},
tags: { endpoint: 'GetUser' },
});
client.close();
}
Expected output:
✓ status is OK
gRPC response: {"id":1,"name":"Alice","email":"alice@example.com"}
Prevention Tips
- Load protobuf files with
client.load()before making any RPC calls - Use
{ plaintext: true }for local development, TLS for production - Handle gRPC errors with try/catch and status code checks
- Close the client connection after each VU iteration
- Use tags for per-endpoint gRPC metrics
Common Mistakes with grpc
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
- Misunderstanding that
Stringis[Char]with poor performance for large text operations - Using
foldlinstead offoldl'causing stack overflow on large lists
These mistakes appear frequently in real-world K6 code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro