grafana/k6 · error

TestRunID of the test is required

Error message

TestRunID of the test is required

What it means

Returned by deriveMetricsURL (output/cloud/expv2/metrics_client.go:44-46) when the test run ID is an empty string. The v2 ingestion URL embeds the run ID as its final path segment (.../v2/metrics/<testRunID>, line 47), so an empty ID would produce a malformed URL and metrics would go nowhere; the guard fails fast instead. Hit from Output.Start (output.go:134) in the legacy derivation path (when no explicit metrics client/URL were injected), wrapped as 'failed to derive the metrics push URL: TestRunID of the test is required'.

Source

Thrown at output/cloud/expv2/metrics_client.go:45

	httpClient metricsHTTPClient
	url        string
}

// deriveMetricsURL builds the v2 metrics-ingestion URL from the Cloud
// service base URL, used when no explicit push URL was provided.
//
// The cloudapi.Client works across different versions of the API: test
// lifecycle management is under /v1 while metrics ingestion is /v2.
// The client has /v1 hard-coded, so we trim it and replace with /v2.
// A versioned client would be better but it would require a breaking
// change, and other services (e.g. k6-operator) depend on it, so we want
// to stabilize the API first.
func deriveMetricsURL(baseURL, testRunID string) (string, error) {
	if !strings.HasSuffix(baseURL, "/v1") {
		return "", errors.New("a /v1 suffix is expected in the Cloud service's BaseURL path")
	}
	if testRunID == "" {
		return "", errors.New("TestRunID of the test is required")
	}
	return strings.TrimSuffix(baseURL, "/v1") + "/v2/metrics/" + testRunID, nil
}

// newMetricsClientWithURL builds a metricsClient with an explicit push URL.
// It is the single metricsClient constructor: callers that need the
// host-derived URL compute it via deriveMetricsURL first.
func newMetricsClientWithURL(c metricsHTTPClient, url string) (*metricsClient, error) {
	if url == "" {
		return nil, errors.New("metrics push URL is required")
	}
	return &metricsClient{
		httpClient: c,
		url:        url,
	}, nil
}

// Push the provided metrics for the given test run ID. The context cancels the

View on GitHub (pinned to 93accf6570)

Solutions

  1. Set K6_CLOUDRUN_TEST_RUN_ID to the externally provisioned test run reference when pushing to a pre-created run
  2. Or use the normal k6 cloud / token flow where the client creates the test run and Start() receives a non-empty ID

Example fix

# before
K6_CLOUD_METRICS_PUSH_URL=https://ingest.example/v2/metrics \
K6_CLOUD_TEST_RUN_TOKEN=*** k6 run -o cloud script.js

# after
K6_CLOUD_METRICS_PUSH_URL=https://ingest.example/v2/metrics \
K6_CLOUD_TEST_RUN_TOKEN=*** \
K6_CLOUDRUN_TEST_RUN_ID=12345 k6 run -o cloud script.js
Defensive patterns

Strategy: validation

Validate before calling

# shell: token-ingestion mode requires a run ID
if [ -n "$K6_CLOUD_METRICS_PUSH_URL" ] && [ -z "$K6_CLOUDRUN_TEST_RUN_ID" ]; then
  echo "K6_CLOUDRUN_TEST_RUN_ID is required when pushing to a pre-provisioned run"; exit 1
fi

Prevention

When it happens

Trigger: The expv2 output starting without a test run reference: e.g. providing K6_CLOUD_METRICS_PUSH_URL + K6_CLOUD_TEST_RUN_TOKEN but omitting K6_CLOUDRUN_TEST_RUN_ID (internal/output/cloud/output.go reads testRunID from that key), or programmatic use of the output where SetTestRunID-equivalent setup was skipped before Start().

Common situations: Direct-to-ingestion setups (token mode) where the run is provisioned externally but the ID env var is missing from CI; wrappers (k6-operator, custom harnesses) that construct the cloud output without wiring the run ID.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/4f13f84b84ea0817. Report an issue: GitHub.