{"record":{"id":"a5afdb5d227bcd33","repo":"grafana/k6","slug":"no-grpc-connection-you-must-call-connect-first","errorCode":null,"errorMessage":"no gRPC connection, you must call connect first","messagePattern":"no gRPC connection, you must call connect first","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/client.go","lineNumber":387,"sourceCode":"\t}()\n\n\treturn promise, nil\n}\n\n// buildInvokeRequest creates a new InvokeRequest from the given method name, request object and parameters\nfunc (c *Client) buildInvokeRequest(\n\tmethod string,\n\treq sobek.Value,\n\tparams sobek.Value,\n) (grpcext.InvokeRequest, error) {\n\tgrpcReq := grpcext.InvokeRequest{}\n\n\tstate := c.vu.State()\n\tif state == nil {\n\t\treturn grpcReq, common.NewInitContextError(\"invoking RPC methods in the init context is not supported\")\n\t}\n\tif c.conn == nil {\n\t\treturn grpcReq, errors.New(\"no gRPC connection, you must call connect first\")\n\t}\n\tif method == \"\" {\n\t\treturn grpcReq, errors.New(\"method to invoke cannot be empty\")\n\t}\n\tif method[0] != '/' {\n\t\tmethod = \"/\" + method\n\t}\n\tmethodDesc := c.mds[method]\n\tif methodDesc == nil {\n\t\treturn grpcReq, fmt.Errorf(\"method %q not found in file descriptors\", method)\n\t}\n\n\tp, err := newCallParams(c.vu, params)\n\tif err != nil {\n\t\treturn grpcReq, fmt.Errorf(\"invalid GRPC's client.invoke() parameters: %w\", err)\n\t}\n\n\t// k6 GRPC Invoke's default timeout is 2 minutes","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/grafana/k6/blob/8d06114777191d21ef885d05c5f8aa9e1ed838ae/internal/js/modules/k6/grpc/client.go#L369-L405","documentation":"Every client.invoke(method, request) goes through buildInvokeRequest, which first verifies a VU state exists and then that c.conn is set. c.conn is only assigned by a successful client.connect(), so invoking before connecting - or after connect failed - produces this error before the method name is even looked at.","triggerScenarios":"client.invoke('pkg.Service/Method', req) called before any client.connect(addr); calling invoke when connect() threw and the script swallowed the error with try/catch and continued; or forgetting that connect must complete first in each VU/setup that invokes.","commonSituations":"Copy-pasting invoke examples while deleting the connect boilerplate; conditional connect logic (if (needsTls) connect()) that skips the call on one branch; error-handling around connect that logs and proceeds, leaving conn nil.","solutions":["Call client.connect(addr, params) before invoke - it is blocking (no await needed) and returns true on success: const ok = client.connect(addr); if (!ok) throw new Error('connect failed').","Do the connection once per VU or in setup and guard the invoke path on the connect result.","If connect is conditional, initialize a flag (let connected = false) and check it before invoking."],"exampleFix":"// before\nexport default function () {\n  client.invoke('hello.HelloService/SayHello', { name: 'k6' }); // throws: no gRPC connection\n}\n\n// after\nexport default function () {\n  client.connect('grpcbin.k6.io:443');\n  client.invoke('hello.HelloService/SayHello', { name: 'k6' });\n}","handlingStrategy":"validation","validationCode":"// connect() is blocking and returns a boolean - assert it before invoking\nconst connected = client.connect('grpcbin.k6.io:443');\nif (!connected) {\n  throw new Error(`failed to connect to gRPC server`);\n}\nclient.invoke('hello.HelloService/SayHello', { name: 'k6' });","typeGuard":null,"tryCatchPattern":"try {\n  client.invoke(method, req);\n} catch (e) {\n  if (/must call connect first/.test(e.message)) {\n    throw new Error('gRPC client not connected - call client.connect() before invoke()');\n  }\n  throw e;\n}","preventionTips":["Connect once per VU (or in setup) and store the result in a module-level flag.","Never swallow connect() exceptions - a silent failure leaves conn nil and every invoke broken.","Order boilerplate as: load (init) -> connect (setup/VU) -> invoke."],"tags":["k6","grpc","connect","client-not-connected","invoke"],"backgroundTag":"client-not-connected","analyzedSha":"8d06114777191d21ef885d05c5f8aa9e1ed838ae","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}