grafana/k6 · error
empty gRPC client
Error message
empty gRPC client
What it means
k6's gRPC module validates the first argument of the `new grpc.Stream(client, method, params)` constructor via the internal extractClient helper (internal/js/modules/k6/grpc/grpc.go:169). "empty gRPC client" means the value passed as the client was null or undefined, so there is no client object to build the stream on. The Stream constructor wraps it as "invalid GRPC Stream's client: empty gRPC client" and throws, aborting the iteration.
Source
Thrown at internal/js/modules/k6/grpc/grpc.go:171
tagsAndMeta: &p.TagsAndMeta,
}
defineStream(rt, s)
err = s.beginStream(p)
if err != nil {
s.tq.Close()
common.Throw(rt, err)
}
return s.obj
}
// extractClient extracts & validates a grpc.Client from a sobek.Value.
func extractClient(v sobek.Value, rt *sobek.Runtime) (*Client, error) {
if common.IsNullish(v) {
return nil, errors.New("empty gRPC client")
}
client, ok := v.ToObject(rt).Export().(*Client)
if !ok {
return nil, errors.New("not a gRPC client")
}
if client.conn == nil {
return nil, errors.New("no gRPC connection, you must call connect first")
}
return client, nil
}
View on GitHub (pinned to 93accf6570)
Solutions
- Pass a `new grpc.Client()` instance as the first argument: `new grpc.Stream(client, method, params)`
- Check that the client variable is defined at the call site (typo/scoping bug)
- Make sure `client.connect(addr)` was called before constructing the Stream
Example fix
// before
const stream = new grpc.Stream(null, '/hello.HelloService/SayHello');
// after
const client = new grpc.Client();
client.connect('grpcbin.test-loadimpact.com:443');
const stream = new grpc.Stream(client, '/hello.HelloService/SayHello'); Defensive patterns
Strategy: type-guard
Validate before calling
if (!client) { throw new Error('gRPC client is not initialized'); } Type guard
const isGrpcClient = (v) => !!v && v instanceof grpc.Client;
Try / catch
try {
const stream = new grpc.Stream(client, method);
} catch (e) {
if (String(e.message).includes('empty gRPC client')) throw new Error('Stream created before a client was passed');
throw e;
} Prevention
- Always create and connect the client in one helper function so the Stream call site always receives a live client
- Lint for `new grpc.Stream(` with fewer than 2 arguments
- Keep client construction in init or at the top of the iteration, never conditionally without a default
When it happens
Trigger: Calling `new grpc.Stream()` with no arguments, or `new grpc.Stream(null, '/pkg.Service/Method')` / `new grpc.Stream(undefined, ...)` — i.e. the first argument is nullish.
Common situations: Refactoring where the client variable is out of scope or misspelled; copy-pasting examples written for the older synchronous `grpc.invoke` API into the newer Stream API and forgetting the client argument; conditional code paths that leave the client variable undefined.
Related errors
- predicate function is not callable
- not a gRPC client
- no gRPC connection, you must call connect first
- must be an object with key-value pairs
- exported 'setup' must be a function
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/cff5f40986a331f7.
Report an issue: GitHub.