{"record":{"id":"52d2ca1cc2560170","repo":"grafana/k6","slug":"request-cannot-be-nil","errorCode":null,"errorMessage":"request cannot be nil","messagePattern":"request cannot be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/client.go","lineNumber":380,"sourceCode":"\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\n\tif p.Timeout == time.Duration(0) {\n\t\tp.Timeout = 2 * time.Minute\n\t}\n\n\tif req == nil {\n\t\treturn grpcReq, errors.New(\"request cannot be nil\")\n\t}\n\n\tobject := req.ToObject(c.vu.Runtime())\n\n\tvar stack []*sobek.Object\n\tnormalized, err := normalizeNumberStrings(object, c.vu.Runtime(), stack)\n\tif err != nil {\n\t\treturn grpcReq, fmt.Errorf(\"unable to normalize number strings: %w\", err)\n\t}\n\n\tb, err := normalized.ToObject(c.vu.Runtime()).MarshalJSON()\n\tif err != nil {\n\t\treturn grpcReq, fmt.Errorf(\"unable to serialise request object: %w\", err)\n\t}\n\n\tp.SetSystemTags(state, c.addr, method)\n\n\treturn grpcext.InvokeRequest{","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/client.go#L362-L398","documentation":"buildInvokeRequest requires a request value: a nil sobek.Value (the second argument missing entirely from the JS call) is rejected. Unlike some k6 APIs, no default empty message is synthesized -- even RPCs whose request type is google.protobuf.Empty must pass an explicit object.","triggerScenarios":"client.invoke('/pkg.Svc/Method') with only one argument; client.asyncInvoke(method) without a request; the request argument dropped while refactoring call sites.","commonSituations":"Health checks and other Empty-request RPCs where users omit the argument because there is nothing to send; parameter object accidentally consumed as the request argument.","solutions":["Always pass a request object, using {} for empty messages: client.invoke('/grpc.health.v1.Health/Check', {})","For typed stubs, default the parameter: invoke(m, req ?? {})"],"exampleFix":"// before\nclient.invoke('/grpc.health.v1.Health/Check');\n\n// after\nclient.invoke('/grpc.health.v1.Health/Check', {});","handlingStrategy":"validation","validationCode":"client.invoke(method, req ?? {}); // request argument is mandatory; {} for Empty messages","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass the second argument, even for Empty-request RPCs","Default at wrapper level: const invoke = (m, r = {}) => client.invoke(m, r)","Remember params is the third argument -- do not shift it into the request slot"],"tags":["grpc","invoke","request","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}