grafana/k6 · error
unexpected HTTP error from %s: %d %s
Error message
unexpected HTTP error from %s: %d %s
What it means
CheckResponse returns this error when the cloud API replies with a non-2xx status whose body cannot be unmarshalled into the expected ResponseError JSON, and the status is not one that httperr.ClassifyStatus maps to a known error (it handles 401 Unauthorized and 403 Forbidden). It is the last-resort message: it preserves the request URL, the numeric status code, and the status text so the failure can still be diagnosed.
Source
Thrown at internal/cloudapi/v6/client.go:90
if r == nil {
return errUnknown
}
if c := r.StatusCode; c >= 200 && c <= 299 {
return nil
}
data, err := io.ReadAll(r.Body)
if err != nil {
return err
}
var payload ResponseError
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.Response = r
return payload
}
View on GitHub (pinned to 93accf6570)
Solutions
- Read the URL and status in the message: 5xx usually means a transient gateway/Cloud issue, so retry after a short wait
- Verify K6_CLOUD_HOST and the stack URL point at the real API host (e.g. https://<stack>.grafana.net)
- If a proxy/WAF sits in the path, bypass it or allowlist the k6 API endpoints
- For persistent 4xx, compare the request URL against the API docs to find the misrouted endpoint
Example fix
# before K6_CLOUD_HOST=http://internal-proxy:8080 k6 cloud script.js # after unset K6_CLOUD_HOST k6 cloud script.js # uses the stack URL from `k6 cloud login`
Defensive patterns
Strategy: retry
Try / catch
if err := client.UploadTest(ctx, name, projectID, arc); err != nil {
var re cloudapiv6.ResponseError
if errors.As(err, &re) {
// structured API error: handle by re.Response.StatusCode
} else if strings.Contains(err.Error(), "unexpected HTTP error") {
// unclassified status with non-JSON body: retry 5xx with backoff, escalate 4xx
}
} Prevention
- Pin K6_CLOUD_HOST / stack URL to the official API host rather than a proxy
- Allowlist *.grafana.net through corporate proxies and WAFs
- Treat unclassified 5xx bodies as transient: retry with exponential backoff before failing a pipeline
When it happens
Trigger: Any cloudapiv6 call (ValidateToken, UploadTest, StartTest, list commands) receives an unexpected status such as 502/503/504 or 418 with a non-JSON body (HTML error page, plain text, empty), so both json.Unmarshal and ClassifyStatus fail to produce a structured error.
Common situations: A corporate proxy, service mesh, or WAF intercepting requests to the Grafana Cloud host and returning an HTML block page; transient gateway 502/503 during a Grafana Cloud incident; K6_CLOUD_HOST pointing at a non-API endpoint that serves HTML.
Related errors
- unexpected HTTP error from %s: %d %s
- decoding response: %w
- notify test run completed: %w
- start local execution: %w
- stack ID %d overflows int32
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/21bf1b2f5e8bafa1.
Report an issue: GitHub.