{"record":{"id":"88c4f218d0290791","repo":"grafana/k6","slug":"couldn-t-open-protoset-w","errorCode":null,"errorMessage":"couldn't open protoset: %w","messagePattern":"couldn't open protoset: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/client.go","lineNumber":107,"sourceCode":"\treturn c.convertToMethodInfo(fdset)\n}\n\n// LoadProtoset will parse the given protoset file (serialized FileDescriptorSet) and make the file\n// descriptors available to request.\nfunc (c *Client) LoadProtoset(protosetPath string) ([]MethodInfo, error) {\n\tif c.vu.State() != nil {\n\t\treturn nil, errors.New(\"load must be called in the init context\")\n\t}\n\n\tinitEnv := c.vu.InitEnv()\n\tif initEnv == nil {\n\t\treturn nil, errors.New(\"missing init environment\")\n\t}\n\n\tabsFilePath := initEnv.GetAbsFilePath(protosetPath)\n\tfdsetFile, err := initEnv.FileSystems[\"file\"].Open(absFilePath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"couldn't open protoset: %w\", err)\n\t}\n\n\tdefer func() { _ = fdsetFile.Close() }()\n\tfdsetBytes, err := io.ReadAll(fdsetFile)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"couldn't read protoset: %w\", err)\n\t}\n\n\tfdset := &descriptorpb.FileDescriptorSet{}\n\tif err = proto.Unmarshal(fdsetBytes, fdset); err != nil {\n\t\treturn nil, fmt.Errorf(\"couldn't unmarshal protoset file %s: %w\", protosetPath, err)\n\t}\n\n\treturn c.convertToMethodInfo(fdset)\n}\n\n// Note: this function was lifted from `lib/options.go`\nfunc decryptPrivateKey(key, password []byte) ([]byte, error) {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/client.go#L89-L125","documentation":"grpc.Client.load() (init context only) resolves the protoset path against the script's directory and opens it from the init filesystem (initEnv.FileSystems['file']); an Open failure is wrapped as 'couldn't open protoset' (internal/js/modules/k6/grpc/client.go:107). This is purely a file-location problem - distinct from read or unmarshal failures on the same call.","triggerScenarios":"client.load('./service.protoset') where the file does not exist at the resolved path: typo, wrong case, file in another directory, or the protoset not shipped alongside the script (k6 archive, Docker image, CI checkout).","commonSituations":"Running k6 from a different working directory; CI jobs copying the script but not sibling files; Docker images missing the ADD/COPY for the protoset; case-sensitive filesystems exposing path-case mistakes.","solutions":["Verify the path relative to the script file (not the CWD) and its exact case","Ensure the protoset is deployed with the script (COPY in Docker, included when archiving)","Drop the protoset and use server reflection instead: client.connect(addr, { reflect: true })"],"exampleFix":"// before\nconst methods = grpcClient.load('../pb/service.protoset'); // wrong directory\n\n// after\nconst methods = grpcClient.load('./pb/service.protoset');\n// or skip the file entirely:\n// grpcClient.connect(addr, { reflect: true })","handlingStrategy":"validation","validationCode":"// fail fast with a clearer error before load()\ntry {\n  open('./pb/service.protoset'); // sync builtin open(); throws if the file is missing\n} catch (e) {\n  throw new Error(`protoset missing next to the script: ${e.message}`);\n}\nconst methods = client.load('./pb/service.protoset');","typeGuard":null,"tryCatchPattern":"try {\n  client.load('./pb/service.protoset');\n} catch (e) {\n  if (/couldn't open protoset/.test(e.message)) { /* fix path or fall back to reflect: true */ }\n  throw e;\n}","preventionTips":["Keep protosets next to the script and reference them relatively","COPY protosets explicitly in Dockerfiles and CI artifacts","Prefer reflect: true when the file logistics are fragile"],"tags":["grpc","k6","protoset","file-not-found"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}