{"record":{"id":"30d154439729dd0a","repo":"grafana/k6","slug":"missing-init-environment","errorCode":null,"errorMessage":"missing init environment","messagePattern":"missing init environment","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/client.go","lineNumber":54,"sourceCode":"type Client struct {\n\tmds  map[string]protoreflect.MethodDescriptor\n\tconn *grpcext.Conn\n\tvu   modules.VU\n\taddr string\n\n\ttypes    *protoregistry.Types\n\ttypesMtx sync.Mutex\n}\n\n// Load will parse the given proto files and make the file descriptors available to request.\nfunc (c *Client) Load(importPaths []string, filenames ...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\t// If no import paths are specified, use the current working directory\n\tif len(importPaths) == 0 {\n\t\timportPaths = append(importPaths, initEnv.CWD.Path)\n\t}\n\n\tfor i, s := range importPaths {\n\t\t// Clean file scheme as it is the only supported scheme and the following APIs do not support them\n\t\timportPaths[i] = strings.TrimPrefix(s, \"file://\")\n\t}\n\n\tresolver := protocompile.WithStandardImports(&protocompile.SourceResolver{\n\t\tImportPaths: importPaths,\n\t\tAccessor: func(filename string) (io.ReadCloser, error) {\n\t\t\tabsFilePath := initEnv.GetAbsFilePath(filename)\n\t\t\treturn initEnv.FileSystems[\"file\"].Open(absFilePath)\n\t\t},","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/client.go#L36-L72","documentation":"After passing the init-context check, grpc Client.Load requires a non-nil init environment (vu.InitEnv()) to resolve import paths and the file filesystem. If the VU was created without an InitEnv -- typical in unit tests, embedded runners, or extensions that fabricate VUs -- loading fails with this error.","triggerScenarios":"Calling Load on a Client whose VU has no InitEnv: constructing the module/VU in Go tests without lib.InitEnv, or invoking Load in a custom execution context that skipped init.","commonSituations":"Extension authors writing unit tests for gRPC helpers; runners that only exercise the VU phase; in normal JS scripts this is nearly unreachable because the state check fires first.","solutions":["In Go tests, populate the VU's InitEnvField with a real *lib.InitEnv (including FileSystems[\"file\"])","Ensure Load is called during the init phase where the runtime provides the environment","Report a clearer upstream error if you wrap this API in an extension"],"exampleFix":"// Go test harness: before, InitEnvField is nil -> \"missing init environment\"\n// after\nruntime.VU.InitEnvField = &lib.InitEnv{\n    CWD:        &url.URL{Scheme: \"file\", Path: \"/tmp/project/\"},\n    FileSystems: map[string]fsext.Fs{\"file\": fsext.NewOsFs()},\n}","handlingStrategy":"validation","validationCode":"// Go: guard before calling\nif vu.InitEnv() == nil {\n    return fmt.Errorf(\"cannot load protos: VU has no init environment (init phase required)\")\n}\nclient.Load(importPaths, files...)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["In extension tests, always build the module VU with a populated lib.InitEnv","Call Load only during the init phase in embedded runners","Wrap this k6 API with your own descriptive error so users are not puzzled"],"tags":["grpc","go-api","environment","testing"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}