grafana/k6 · error

archive upload failed: %d %s: %s

Error message

archive upload failed: %d %s: %s

What it means

Same rejection path as the empty-body variant, but here the response body was readable and is appended verbatim (internal/cloudapi/provisioning/api.go:119-122). For S3-style storage this is typically an XML error document whose <Code> element names the exact cause - ExpiredToken, AccessDenied, SignatureDoesNotMatch, EntityTooLarge - making this the most diagnostic of the upload failures.

Source

Thrown at internal/cloudapi/provisioning/api.go:120

	req.Header.Set("Content-Type", "application/x-tar")
	req.ContentLength = int64(len(body))

	resp, err := c.doWithRetry(req)
	if err != nil {
		return fmt.Errorf("uploading archive: %w", err)
	}
	defer func() {
		_, _ = io.Copy(io.Discard, resp.Body)
		_ = resp.Body.Close()
	}()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		respBody, readErr := io.ReadAll(resp.Body)
		if readErr != nil || len(respBody) == 0 {
			return fmt.Errorf("archive upload failed: %d %s",
				resp.StatusCode, http.StatusText(resp.StatusCode))
		}
		return fmt.Errorf("archive upload failed: %d %s: %s",
			resp.StatusCode, http.StatusText(resp.StatusCode), respBody)
	}

	return nil
}

// WaitForTestRunReady polls GET /cloud/v6/test_runs/{id} until the
// backend status becomes "initializing" (signalling that k6 can begin
// local execution). Returns an error if the test run reaches "aborted"
// or "completed" first. Cancellable via context. Logs status transitions
// at Debug level once per change.
//
// If pollInterval is <= 0 the defaultWaitPollInterval is used.
func (c *Client) WaitForTestRunReady(ctx context.Context, testRunID int64, pollInterval time.Duration) error {
	if pollInterval <= 0 {
		pollInterval = defaultWaitPollInterval
	}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Read the <Code> in the appended body: ExpiredToken -> re-run for a fresh URL; SignatureDoesNotMatch -> something altered the URL in transit (bypass the proxy); AccessDenied -> backend/bucket policy, contact cloud support; EntityTooLarge -> shrink the archive
  2. Shrink the archive by removing unnecessary bundled files or using --include-only-env? or k6 archive optimizations; check archive size before upload
  3. Re-run the test - each provisioning issues a fresh presigned URL
  4. If the backend is yours, raise the upload size limit or URL lifetime

Example fix

# before - bundling a huge dataset into the archive
cp ./huge-fixtures/** ./   # tens of MB
k6 cloud run --local-execution script.js   # archive upload failed: 400 ... EntityTooLarge

# after - keep the archive lean; fetch data at runtime
# (remove fixtures from the bundle)
k6 cloud run --local-execution script.js
Defensive patterns

Strategy: retry

Type guard

// classify S3-style XML bodies embedded in the error
func uploadErrCode(errMsg string) string {
    m := regexp.MustCompile(`<Code>([A-Za-z]+)</Code>`).FindStringSubmatch(errMsg)
    if m == nil {
        return ""
    }
    return m[1]
}

Try / catch

if err := c.UploadArchive(ctx, url, body); err != nil {
    switch uploadErrCode(err.Error()) {
    case "ExpiredToken", "AccessDenied":
        // re-run the test for a fresh URL / check backend policy - do not blind-retry this URL
    case "SignatureDoesNotMatch":
        // URL was altered in transit: fix the proxy path first
    case "EntityTooLarge":
        // shrink the archive before retrying
    }
}

Prevention

When it happens

Trigger: SignatureDoesNotMatch after a proxy or client altered query parameters; ExpiredToken when the upload starts after the presigned window closed; AccessDenied from bucket/IAM policy on the backend; EntityTooLarge when the archive exceeds the bucket or backend limit.

Common situations: Corporate proxies normalizing/encoding URLs differently; long-running CI jobs reusing a URL issued minutes earlier; large archives (big bundled assets or many files) exceeding upload limits.

Related errors


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