grafana/k6 · error
both K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN m
Error message
both K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN must be set together
What it means
Thrown by applyExternalProvisioningCreds when exactly one of K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN is set (the `(pushURL == "") != (token == "")` XOR check). An externally-provisioned cloud run needs both the metrics endpoint and the scoped token that authenticates to it.
Source
Thrown at internal/cmd/outputs_cloud.go:225
// values the self-provision flow obtains from the provisioning response.
// It requires both-or-neither and, when both are present, sets them on conf
// (so downstream consumers such as the log pusher see them) and bakes them
// into the serialized cloud config that the Output reads. It also reads the
// K6_CLOUD_LOGS_* log-push config, which the external flow supplies the same
// way.
func applyExternalProvisioningCreds(
gs *state.GlobalState, test *loadedAndConfiguredTest, conf *cloudapi.Config,
) error {
// The log-push config is env-supplied for an external run and likewise not
// env-bound on the Config, so read it explicitly here (before the checks
// below, which require the token when a logs URL is set).
if err := applyExternalLogsConfig(gs, conf); err != nil {
return err
}
pushURL := gs.Env["K6_CLOUD_METRICS_PUSH_URL"]
token := gs.Env["K6_CLOUD_TEST_RUN_TOKEN"]
if (pushURL == "") != (token == "") {
return errors.New("both K6_CLOUD_METRICS_PUSH_URL and " +
"K6_CLOUD_TEST_RUN_TOKEN must be set together")
}
// A logs push URL is authenticated with the same scoped token, so reject a
// logs URL supplied without it rather than silently streaming nothing.
if token == "" && conf.LogsPushURL.Valid && conf.LogsPushURL.String != "" {
return errors.New("K6_CLOUD_LOGS_PUSH_URL requires K6_CLOUD_TEST_RUN_TOKEN")
}
if pushURL == "" {
return nil
}
conf.MetricsPushURL = null.StringFrom(pushURL)
conf.TestRunToken = null.StringFrom(token)
raw, err := cloudConfToRawMessage(*conf)
if err != nil {
return fmt.Errorf("could not serialize cloud configuration: %w", err)
}
if test.derivedConfig.Collectors == nil {View on GitHub (pinned to 93accf6570)
Solutions
- Export both variables together, exactly as emitted by the cloud UI/CLI (they are generated as a pair)
- If an external run was not intended, unset both and authenticate with K6_CLOUD_TOKEN instead
- Verify the CI secret manager did not redact, truncate, or rename K6_CLOUD_TEST_RUN_TOKEN
Example fix
# before export K6_CLOUD_METRICS_PUSH_URL=https://.../api/v1/write k6 run --out cloud script.js # after export K6_CLOUD_METRICS_PUSH_URL=https://.../api/v1/write export K6_CLOUD_TEST_RUN_TOKEN=eyJ... k6 run --out cloud script.js
Defensive patterns
Strategy: validation
Validate before calling
# Both or neither if [ -n "$K6_CLOUD_METRICS_PUSH_URL" ] && [ -z "$K6_CLOUD_TEST_RUN_TOKEN" ] || [ -z "$K6_CLOUD_METRICS_PUSH_URL" ] && [ -n "$K6_CLOUD_TEST_RUN_TOKEN" ]; then echo "K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN must be set together" >&2; exit 1; fi
Prevention
- Export external-provisioning env vars as one block from the cloud-provided command
- Name CI secrets exactly K6_CLOUD_TEST_RUN_TOKEN and verify masking does not empty them
- Add a startup env check in wrapper scripts so the failure is caught before the test starts
When it happens
Trigger: Launching k6 with a PushRefID-based external run where K6_CLOUD_METRICS_PUSH_URL is exported but K6_CLOUD_TEST_RUN_TOKEN is missing (or the reverse).
Common situations: CI secret masking/redaction stripping the token env var; copying only half of a Grafana Cloud 'external run' command; push URL set globally in CI while the token is passed per-job (or vice versa).
Related errors
- K6_CLOUD_LOGS_PUSH_URL requires K6_CLOUD_TEST_RUN_TOKEN
- Run `k6 cloud login` to authenticate, or check the docs for
- access token not configured
- %s: %w.\n%w
- default stack configured but the default project ID is not a
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/ad409226c652d004.
Report an issue: GitHub.