grafana/k6 · error

unexpected HTTP error from %s: %d %s

Error message

unexpected HTTP error from %s: %d %s

What it means

CheckResponse (cloudapi/client.go:190-220) wraps every non-2xx response from the cloud API. It first tries to parse the body as {"error":...} JSON, then falls back to httperr.ClassifyStatus for well-known statuses; when both fail you get this generic message carrying the request URL, numeric status, and reason phrase. It signals an error response the client cannot interpret - typically a non-JSON error page from something between k6 and the API.

Source

Thrown at cloudapi/client.go:211

	}

	if c := r.StatusCode; c >= 200 && c <= 299 {
		return nil
	}

	data, err := io.ReadAll(r.Body)
	if err != nil {
		return err
	}

	var payload struct {
		Error ResponseError `json:"error"`
	}
	if err := json.Unmarshal(data, &payload); err != nil {
		if classified := httperr.ClassifyStatus(r.StatusCode); classified != nil {
			return classified
		}
		return fmt.Errorf(
			"unexpected HTTP error from %s: %d %s",
			r.Request.URL,
			r.StatusCode,
			http.StatusText(r.StatusCode),
		)
	}
	payload.Error.Response = r
	return payload.Error
}

func shouldRetry(resp *http.Response, err error, attempt, maxAttempts int) bool {
	if attempt >= maxAttempts {
		return false
	}

	if resp == nil || err != nil {
		return true
	}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Reproduce with curl -v against the exact URL printed in the error and inspect the raw response
  2. Verify K6_CLOUD_HOST is the API endpoint, not the web UI (re-run 'k6 cloud login' to reset it)
  3. Check HTTP_PROXY/HTTPS_PROXY/NO_PROXY and try bypassing the proxy for the cloud host
  4. If the status is 5xx from the cloud itself, check the Grafana Cloud status page and retry

Example fix

# before
export K6_CLOUD_HOST=https://k6.io   # web site, not the API
k6 cloud run script.js   # unexpected HTTP error from https://k6.io/...: 404 Not Found

# after
export K6_CLOUD_HOST=https://api.cloud.k6.io
k6 cloud run script.js
Defensive patterns

Strategy: retry

Validate before calling

# pre-flight: assert the configured host answers like the cloud API, not a proxy page
curl -sS -o /dev/null -w '%{http_code} %{content_type}\n' "$K6_CLOUD_HOST/v1/test-runs" -H "Authorization: Token $K6_CLOUD_TOKEN"

Try / catch

err := client.Do(req, &response)
if err != nil {
    var re *cloudapi.ResponseError
    if errors.As(err, &re) {
        // structured cloud error: inspect re.Response.StatusCode
    } else if strings.HasPrefix(err.Error(), "unexpected HTTP error from") {
        // unclassified/proxy response: retry with backoff, then surface URL+status to the operator
    }
}

Prevention

When it happens

Trigger: Any cloudapi request (login, create test run, push) where an intermediary returns an unusual status with an HTML/plain body: nginx 502/504 pages, a WAF block page, a captive portal, or K6_CLOUD_HOST pointing at a service that is not the k6 cloud API (e.g. the web app instead of the API host).

Common situations: Corporate egress proxies or SSL-inspection appliances rewriting responses; K6_CLOUD_HOST typo ( Hits the Grafana UI host instead of the API ); an outage page served with a status httperr does not classify.

Related errors


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