{"record":{"id":"66c956fdd3118971","repo":"grafana/k6","slug":"no-grpc-connection-you-must-call-connect-first-66c956","errorCode":null,"errorMessage":"no gRPC connection, you must call connect first","messagePattern":"no gRPC connection, you must call connect first","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/grpc.go","lineNumber":180,"sourceCode":"\t\tcommon.Throw(rt, err)\n\t}\n\n\treturn s.obj\n}\n\n// extractClient extracts & validates a grpc.Client from a sobek.Value.\nfunc extractClient(v sobek.Value, rt *sobek.Runtime) (*Client, error) {\n\tif common.IsNullish(v) {\n\t\treturn nil, errors.New(\"empty gRPC client\")\n\t}\n\n\tclient, ok := v.ToObject(rt).Export().(*Client)\n\tif !ok {\n\t\treturn nil, errors.New(\"not a gRPC client\")\n\t}\n\n\tif client.conn == nil {\n\t\treturn nil, errors.New(\"no gRPC connection, you must call connect first\")\n\t}\n\n\treturn client, nil\n}\n","sourceCodeStart":162,"sourceCodeEnd":185,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/grpc.go#L162-L185","documentation":"After a `grpc.Client` is created, its internal `conn` field is nil until `connect()` succeeds (and `close()` resets it to nil). extractClient (internal/js/modules/k6/grpc/grpc.go:179) rejects such a disconnected client with \"no gRPC connection, you must call connect first\" when it is passed to `new grpc.Stream(client, ...)`. It means you have a valid Client object that has no live connection.","triggerScenarios":"Creating `const client = new grpc.Client()` and constructing a Stream without ever calling `client.connect(addr)`; reusing a client after `client.close()` (conn is reset to nil); a connect attempt that failed before the Stream was built.","commonSituations":"Forgetting connect() when splitting setup across functions; reusing a shared client across iterations after closing it at the end of a previous iteration; connect failure being swallowed earlier in the code.","solutions":["Call `client.connect(address, params)` and let it finish before `new grpc.Stream(...)`","If the client was closed, create a new Client and connect again","Ensure connect() is not inside a try/catch that silently continues on failure"],"exampleFix":"// before\nconst client = new grpc.Client();\nconst stream = new grpc.Stream(client, '/svc/Method');\n\n// after\nconst client = new grpc.Client();\nclient.connect('localhost:8080');\nconst stream = new grpc.Stream(client, '/svc/Method');","handlingStrategy":"validation","validationCode":"const client = new grpc.Client();\nclient.connect(addr); // throws on failure — do not swallow\n// immediately usable; keep a single owner for the client lifecycle","typeGuard":null,"tryCatchPattern":"try {\n  const stream = new grpc.Stream(client, method);\n} catch (e) {\n  if (String(e.message).includes('must call connect first')) {\n    client.connect(addr); // or re-create the client\n    throw e; // next iteration will succeed, or retry here\n  }\n  throw e;\n}","preventionTips":["Call connect() immediately after `new grpc.Client()` in the same statement block","Do not call client.close() mid-iteration if the client is reused by later iterations — close in teardown or at end-of-life only","Never wrap connect() in a try/catch that continues execution on failure"],"tags":["grpc","javascript","lifecycle","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}