{"record":{"id":"bd8d6ea3d31c19c2","repo":"grafana/k6","slug":"stack-url-is-required-to-validate-token","errorCode":null,"errorMessage":"stack URL is required to validate token","messagePattern":"stack URL is required to validate token","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/v6/api.go","lineNumber":190,"sourceCode":"\n\tzones := make([]LoadZone, 0, len(res.Value))\n\tfor _, zone := range res.Value {\n\t\tzones = append(zones, LoadZone{\n\t\t\tID:           zone.Id,\n\t\t\tK6LoadZoneID: zone.K6LoadZoneId,\n\t\t\tName:         zone.Name,\n\t\t\tPublic:       zone.Public,\n\t\t\tAvailable:    zone.Available,\n\t\t})\n\t}\n\n\treturn zones, nil\n}\n\n// ValidateToken validates the cloud authentication token.\nfunc (c *Client) ValidateToken(ctx context.Context, stackURL string) (_ *k6cloud.AuthenticationResponse, err error) {\n\tif stackURL == \"\" {\n\t\treturn nil, errors.New(\"stack URL is required to validate token\")\n\t}\n\tif _, err := url.Parse(stackURL); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid stack URL: %w\", err)\n\t}\n\n\tres, hr, err := c.apiClient.AuthorizationAPI.\n\t\tAuth(c.authCtx(ctx)).\n\t\tXStackUrl(stackURL).\n\t\tExecute()\n\tdefer closeResponse(hr, &err)\n\n\tif err := CheckResponse(hr, err); err != nil {\n\t\treturn nil, err\n\t}\n\tif res == nil {\n\t\treturn nil, errUnknown\n\t}\n","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/grafana/k6/blob/01ffac6f245854c1b8adc6a69857c76a15f90022/internal/cloudapi/v6/api.go#L172-L208","documentation":"Defensive guard in Client.ValidateToken: the method needs a stack URL to send as the X-Stack-Url header when validating an API token, and it refuses to proceed when the argument is an empty string. In-tree callers (k6 cloud login) always pass a normalized non-empty URL, so this error is only seen by Go code calling the internal v6 client directly or by wiring bugs.","triggerScenarios":"Calling cloudapiv6 Client.ValidateToken(ctx, \"\") (or with a whitespace/empty-after-trim string) — e.g. building the client in your own tooling and passing an unresolved stack variable. The check happens before any HTTP request is made.","commonSituations":"Custom automation that embeds k6's internal cloudapi package; a stack slug read from an unset environment variable; code that assumes ValidateToken will look up the stack from client config (it does not — the URL must be passed per call).","solutions":["Pass a full stack URL such as https://my-team.grafana.net (or normalize a slug like my-team yourself before calling)","If the stack is optional in your flow, resolve it from config/env first and skip validation when absent","Check the variable feeding the call — an unset env var or empty flag usually produces the empty string"],"exampleFix":"// before\nauthResp, err := client.ValidateToken(ctx, os.Getenv(\"K6_STACK\")) // K6_STACK unset -> error\n\n// after\nstackURL := strings.TrimSpace(os.Getenv(\"K6_STACK\"))\nif stackURL == \"\" {\n    return errors.New(\"K6_STACK must be set to a stack URL or slug\")\n}\nif !strings.Contains(stackURL, \"://\") {\n    stackURL = fmt.Sprintf(\"https://%s.grafana.net\", stackURL)\n}\nauthResp, err := client.ValidateToken(ctx, stackURL)","handlingStrategy":"validation","validationCode":"stackURL := strings.TrimSpace(stackURL)\nif stackURL == \"\" {\n    return errors.New(\"stack URL is required to validate token\")\n}\nif _, err := url.Parse(stackURL); err != nil {\n    return fmt.Errorf(\"invalid stack URL: %w\", err)\n}\nif !strings.Contains(stackURL, \"://\") {\n    stackURL = fmt.Sprintf(\"https://%s.grafana.net\", stackURL)\n}","typeGuard":"func isValidStackURL(s string) bool {\n\ts = strings.TrimSpace(s)\n\tif s == \"\" {\n\t\treturn false\n\t}\n\tu, err := url.Parse(s)\n\treturn err == nil && u.Host != \"\" && (u.Scheme == \"http\" || u.Scheme == \"https\")\n}","tryCatchPattern":null,"preventionTips":["Never pass a raw env var to ValidateToken — trim and default it first","Mirror k6's own normalization: slugs become https://<slug>.grafana.net, full URLs keep scheme+host only","Fail fast in your tooling when the stack variable is unset instead of letting the client reject it later"],"tags":["k6","cloud-api","validation","stack-url","token-validation"],"backgroundTag":"missing-required-argument","analyzedSha":"01ffac6f245854c1b8adc6a69857c76a15f90022","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}