{"record":{"id":"a52aa37d7c5a509c","repo":"grafana/k6","slug":"both-k6-cloud-metrics-push-url-and-k6-cloud-test-r-a52aa3","errorCode":null,"errorMessage":"both K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN must be set together","messagePattern":"both K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN must be set together","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/output/cloud/output.go","lineNumber":243,"sourceCode":"\treturn nil\n}\n\n// Start calls the k6 Cloud API to initialize the test run, and then starts the\n// goroutine that would listen for metric samples and send them to the cloud.\nfunc (out *Output) Start() error {\n\tif out.config.PushRefID.Valid {\n\t\tout.testRunID = out.config.PushRefID.String\n\t}\n\n\tif out.testRunID != \"\" {\n\t\tout.logger.WithField(\"testRunId\", out.testRunID).Debug(\"Directly pushing metrics without init\")\n\n\t\t// Exactly one of the scoped push creds set is a misconfiguration.\n\t\t// The cmd layer already validates this for the externally-provisioned\n\t\t// env case (internal/cmd/outputs_cloud.go); this is the defensive\n\t\t// backstop for any other source (e.g. a hand-written cloud config).\n\t\tif out.config.MetricsPushURL.Valid != out.config.TestRunToken.Valid {\n\t\t\treturn errors.New(\n\t\t\t\t\"both K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN \" +\n\t\t\t\t\t\"must be set together\")\n\t\t}\n\n\t\t// Provisioning-mode push. Armed whenever the scoped push credentials\n\t\t// are present: either k6 self-provisioned (no PushRefID) or an external\n\t\t// service provisioned the run and its creds were injected into the\n\t\t// cloud config by the cmd layer (PushRefID set; that service owns\n\t\t// create/start/notify).\n\t\tif out.config.MetricsPushURL.Valid && out.config.TestRunToken.Valid {\n\t\t\tif err := out.lazyInitProvisioning(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\treturn out.startVersionedOutput()\n\t}\n","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/output/cloud/output.go#L225-L261","documentation":"Thrown during cloud output Start() when the run is in direct-push mode (a testRunID exists, from K6_CLOUD_PUSH_REF_ID or a self-provisioned run) and exactly one of the scoped push credentials is set. The direct-push path requires K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN as a pair; the check is XOR-style (MetricsPushURL.Valid != TestRunToken.Valid) and acts as a defensive backstop behind the cmd-layer validation in internal/cmd/outputs_cloud.go.","triggerScenarios":"Hand-written cloud config where only one of metricsPushURL/testRunToken is present; exporting K6_CLOUD_TEST_RUN_TOKEN in the environment without K6_CLOUD_METRICS_PUSH_URL (or vice versa) while also having a push ref id (K6_CLOUD_PUSH_REF_ID) or otherwise entering the direct-push branch; a Go program constructing output.Params with a partial cloud config JSON.","commonSituations":"Scripts migrated from an older k6 that only needed a token; CI pipelines where the push URL variable was forgotten in one job template; shell profiles that set K6_CLOUD_TEST_RUN_TOKEN globally, surprising later runs; integrations that inject credentials one at a time.","solutions":["Set both variables together: K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN","If you do not intend to push directly, unset BOTH variables so k6 falls back to normal cloud provisioning","Search the environment and .env files for a stray K6_CLOUD_TEST_RUN_TOKEN or K6_CLOUD_METRICS_PUSH_URL: env | grep K6_CLOUD"],"exampleFix":"# before\nexport K6_CLOUD_TEST_RUN_TOKEN=abc123\n# only token set -> error\n\n# after (direct push)\nexport K6_CLOUD_METRICS_PUSH_URL=https://cloudapi.k6.io/api/v1/metrics/push\nexport K6_CLOUD_TEST_RUN_TOKEN=abc123\n\n# after (normal provisioning)\nunset K6_CLOUD_TEST_RUN_TOKEN K6_CLOUD_METRICS_PUSH_URL","handlingStrategy":"validation","validationCode":"# Both or neither — check before running k6:\nset -- $K6_CLOUD_METRICS_PUSH_URL $K6_CLOUD_TEST_RUN_TOKEN\nif [ -n \"$K6_CLOUD_METRICS_PUSH_URL\" ] || [ -n \"$K6_CLOUD_TEST_RUN_TOKEN\" ]; then\n  [ -n \"$K6_CLOUD_METRICS_PUSH_URL\" ] && [ -n \"$K6_CLOUD_TEST_RUN_TOKEN\" ] || { echo 'set both push URL and token, or neither'; exit 1; }\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never export only one of the two direct-push variables in shell profiles or CI templates","Wrap credential injection so related vars are set atomically in one script","env | grep K6_CLOUD in CI job logs (names only) before running k6"],"tags":["k6","cloud","credentials","env-vars","config"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}