{"record":{"id":"4be6d79be7e700aa","repo":"grafana/k6","slug":"token-is-required-to-create-provisioning-api-clien","errorCode":null,"errorMessage":"token is required to create provisioning API client","messagePattern":"token is required to create provisioning API client","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/provisioning/client.go","lineNumber":47,"sourceCode":"\tstackID   int64\n\thost      string\n\tversion   string\n\n\tlogger logrus.FieldLogger\n}\n\n// NewClient returns a new provisioning Client. It internally constructs\n// both a k6cloud.APIClient (for provisioning endpoints) and a v6.Client\n// (for v6 operations like FetchTest). The stackID identifies the\n// Grafana Cloud stack and is required for the stack-scoped requests.\nfunc NewClient(\n\tlogger logrus.FieldLogger,\n\ttoken, host, version string,\n\tstackID int64,\n\ttimeout time.Duration,\n) (*Client, error) {\n\tif token == \"\" {\n\t\treturn nil, fmt.Errorf(\"token is required to create provisioning API client\")\n\t}\n\n\tcfg := clientcfg.New(host, version, \"k6 Cloud API (provisioning).\", timeout)\n\n\tv6c, err := v6.NewClient(logger, token, host, version, timeout)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating v6 client: %w\", err)\n\t}\n\n\tc := &Client{\n\t\tapiClient: k6cloud.NewAPIClient(cfg),\n\t\tv6Client:  v6c,\n\t\ttoken:     token,\n\t\tstackID:   stackID,\n\t\thost:      host,\n\t\tversion:   version,\n\t\tlogger:    logger,\n\t}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/cloudapi/provisioning/client.go#L29-L65","documentation":"provisioning.NewClient (internal/cloudapi/provisioning/client.go:47) refuses to construct a client without an API token because every provisioning and v6 call uses Bearer auth. An empty token means cloud authentication was never configured, and all subsequent requests would fail with confusing 401s.","triggerScenarios":"Running cloud / --local-execution flows without `k6 cloud login` and without K6_CLOUD_TOKEN set; constructing provisioning.NewClient programmatically with an empty token string.","commonSituations":"CI pipelines that forgot to inject the token secret; fresh machines/containers without the k6 Cloud config file; scripts that read the token from an unset variable and pass an empty string.","solutions":["Run `k6 cloud login` to store a token, or export K6_CLOUD_TOKEN with a valid API token","If constructing the client in Go, resolve and check the token before calling NewClient","Verify the env var name and that it has no surrounding whitespace/quotes"],"exampleFix":"# before\nk6 run --local-execution script.js  # no token anywhere\n\n# after\nexport K6_CLOUD_TOKEN=\"<api-token>\"\nk6 run --local-execution script.js","handlingStrategy":"validation","validationCode":"token := os.Getenv(\"K6_CLOUD_TOKEN\")\nif token == \"\" {\n\treturn errors.New(\"K6_CLOUD_TOKEN is empty — run `k6 cloud login` or export the token\")\n}\nclient, err := provisioning.NewClient(logger, token, host, version, stackID, timeout)","typeGuard":"func hasCloudToken(token string) bool { return strings.TrimSpace(token) != \"\" }","tryCatchPattern":"client, err := provisioning.NewClient(logger, token, host, version, stackID, timeout)\nif err != nil {\n\tif strings.Contains(err.Error(), \"token is required\") {\n\t\t// guide the user to login/config, don't surface a raw 401 later\n\t}\n\treturn err\n}","preventionTips":["Resolve and validate the token once at startup, before building clients","Inject K6_CLOUD_TOKEN explicitly in CI rather than relying on stored config","Fail fast with an actionable message instead of constructing a half-configured client"],"tags":["auth","token","configuration","client-construction"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}