{"record":{"id":"f3b18dbdaee36388","repo":"grafana/k6","slug":"cloud-secrets-not-configured-token-not-set","errorCode":null,"errorMessage":"cloud secrets not configured: token not set","messagePattern":"cloud secrets not configured: token not set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/secretsource/cloud/cloud.go","lineNumber":114,"sourceCode":"\tcurrent := cs.configPtr.Load()\n\n\t// Re-use the cached source if the config pointer is unchanged.\n\tif cs.activeCfg == current && (cs.urlSource != nil || cs.initErr != nil) {\n\t\treturn cs.urlSource, cs.initErr\n\t}\n\n\t// (Re-)initialize for the new config.\n\tcs.activeCfg = current\n\tcs.urlSource = nil\n\tcs.initErr = nil\n\n\tif current == nil {\n\t\tcs.initErr = cs.notConfiguredError()\n\t\treturn nil, cs.initErr\n\t}\n\n\tif current.Token == \"\" {\n\t\tcs.initErr = errors.New(\"cloud secrets not configured: token not set\")\n\t\treturn nil, cs.initErr\n\t}\n\n\tif current.Endpoint == \"\" {\n\t\tcs.initErr = errors.New(\"cloud secrets not configured: endpoint not set\")\n\t\treturn nil, cs.initErr\n\t}\n\n\textra := 2 // always: URL template + Authorization header\n\tif current.ResponsePath != \"\" {\n\t\textra = 3\n\t}\n\tenvCopy := make(map[string]string, len(cs.params.Environment)+extra)\n\tmaps.Copy(envCopy, cs.params.Environment)\n\tenvCopy[\"K6_SECRET_SOURCE_URL_URL_TEMPLATE\"] = current.Endpoint\n\tenvCopy[\"K6_SECRET_SOURCE_URL_HEADER_AUTHORIZATION\"] = \"Bearer \" + current.Token\n\tif current.ResponsePath != \"\" {\n\t\tenvCopy[\"K6_SECRET_SOURCE_URL_RESPONSE_PATH\"] = current.ResponsePath","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/secretsource/cloud/cloud.go#L96-L132","documentation":"Returned while initializing the cloud secrets URL source when a secrets configuration exists but its Token field is empty. The token becomes the 'Authorization: Bearer <token>' header used to fetch secrets (envCopy[\"K6_SECRET_SOURCE_URL_HEADER_AUTHORIZATION\"]), so an empty token means every fetch would be unauthorized; k6 fails fast instead.","triggerScenarios":"K6_CLOUD_SECRETS_TOKEN exported as an empty string while K6_CLOUD_SECRETS_ENDPOINT is set; a secrets config JSON/struct with endpoint but blank token; CI secret masking that replaced the token with '' or a placeholder that later strips to empty.","commonSituations":"Vault/secret-manager integrations that inject an empty string when the secret path is wrong; shell quoting bugs (export K6_CLOUD_SECRETS_TOKEN=\"\") in generated CI scripts; tokens stored under a differently-named variable that was never populated.","solutions":["Set K6_CLOUD_SECRETS_TOKEN to a valid cloud token (the same style used for K6_CLOUD_TOKEN)","Verify the variable is non-empty at runtime: [ -n \"$K6_CLOUD_SECRETS_TOKEN\" ] || echo missing","Check the secret-injection step in CI actually resolved the value (no silent empty fallbacks)"],"exampleFix":"# before\nexport K6_CLOUD_SECRETS_ENDPOINT=https://cloudapi.k6.io/v1/secrets\nexport K6_CLOUD_SECRETS_TOKEN=\"\"   # empty -> error\n\n# after\nexport K6_CLOUD_SECRETS_ENDPOINT=https://cloudapi.k6.io/v1/secrets\nexport K6_CLOUD_SECRETS_TOKEN=\"$CLOUD_SECRETS_TOKEN\"","handlingStrategy":"validation","validationCode":"[ -n \"${K6_CLOUD_SECRETS_TOKEN:-}\" ] || { echo 'K6_CLOUD_SECRETS_TOKEN is empty'; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fail the secret-injection step when the resolved value is empty instead of exporting ''","Never use empty-string placeholders for masked secrets in generated env files","Verify token presence (not value) in a CI preflight before k6 starts"],"tags":["k6","cloud","secrets","token","auth","env-vars"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}