grafana/k6 · error
K6_CLOUD_LOGS_PUSH_URL requires K6_CLOUD_TEST_RUN_TOKEN
Error message
K6_CLOUD_LOGS_PUSH_URL requires K6_CLOUD_TEST_RUN_TOKEN
What it means
Logs for a cloud run are pushed to K6_CLOUD_LOGS_PUSH_URL authenticated with the same scoped token as metrics. applyExternalProvisioningCreds rejects a logs URL supplied without K6_CLOUD_TEST_RUN_TOKEN rather than silently streaming nothing.
Source
Thrown at internal/cmd/outputs_cloud.go:231
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 {
test.derivedConfig.Collectors = make(map[string]json.RawMessage)
}
test.derivedConfig.Collectors[builtinOutputCloud.String()] = raw
return nil
}
View on GitHub (pinned to 93accf6570)
Solutions
- Set K6_CLOUD_TEST_RUN_TOKEN alongside K6_CLOUD_LOGS_PUSH_URL (and K6_CLOUD_METRICS_PUSH_URL)
- If you do not want log shipping, unset K6_CLOUD_LOGS_PUSH_URL
- Check that the token was not stripped by secret masking in CI
Example fix
# before export K6_CLOUD_LOGS_PUSH_URL=https://.../logs k6 run --out cloud script.js # after export K6_CLOUD_LOGS_PUSH_URL=https://.../logs 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
if [ -n "$K6_CLOUD_LOGS_PUSH_URL" ] && [ -z "$K6_CLOUD_TEST_RUN_TOKEN" ]; then echo "K6_CLOUD_LOGS_PUSH_URL requires K6_CLOUD_TEST_RUN_TOKEN" >&2; exit 1; fi
Prevention
- Treat the token as mandatory whenever any K6_CLOUD_*_PUSH_URL is present
- Keep cloud log-push config in the same env file as the token so they move together
- Audit CI env files after secret rotation — tokens expire, URLs linger
When it happens
Trigger: Setting K6_CLOUD_LOGS_PUSH_URL (or a LogsPushURL in config) while K6_CLOUD_TEST_RUN_TOKEN is empty and no token is otherwise provisioned.
Common situations: Enabling cloud log shipping piecemeal in CI; a redacted/missing token with the logs URL left in place; per-stage env files where the token line was dropped.
Related errors
- both K6_CLOUD_METRICS_PUSH_URL and K6_CLOUD_TEST_RUN_TOKEN m
- 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/272a090281680cf9.
Report an issue: GitHub.