{"record":{"id":"21bf1b2f5e8bafa1","repo":"grafana/k6","slug":"unexpected-http-error-from-s-d-s-21bf1b","errorCode":null,"errorMessage":"unexpected HTTP error from %s: %d %s","messagePattern":"unexpected HTTP error from (.+?): (.+?) (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloudapi/v6/client.go","lineNumber":90,"sourceCode":"\tif r == nil {\n\t\treturn errUnknown\n\t}\n\n\tif c := r.StatusCode; c >= 200 && c <= 299 {\n\t\treturn nil\n\t}\n\n\tdata, err := io.ReadAll(r.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar payload ResponseError\n\tif err := json.Unmarshal(data, &payload); err != nil {\n\t\tif classified := httperr.ClassifyStatus(r.StatusCode); classified != nil {\n\t\t\treturn classified\n\t\t}\n\t\treturn fmt.Errorf(\n\t\t\t\"unexpected HTTP error from %s: %d %s\",\n\t\t\tr.Request.URL,\n\t\t\tr.StatusCode,\n\t\t\thttp.StatusText(r.StatusCode),\n\t\t)\n\t}\n\tpayload.Response = r\n\treturn payload\n}\n","sourceCodeStart":72,"sourceCodeEnd":100,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/cloudapi/v6/client.go#L72-L100","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nK6_CLOUD_HOST=http://internal-proxy:8080 k6 cloud script.js\n# after\nunset K6_CLOUD_HOST\nk6 cloud script.js  # uses the stack URL from `k6 cloud login`","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := client.UploadTest(ctx, name, projectID, arc); err != nil {\n    var re cloudapiv6.ResponseError\n    if errors.As(err, &re) {\n        // structured API error: handle by re.Response.StatusCode\n    } else if strings.Contains(err.Error(), \"unexpected HTTP error\") {\n        // unclassified status with non-JSON body: retry 5xx with backoff, escalate 4xx\n    }\n}","preventionTips":["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"],"tags":["go","http","cloud-api","proxy","error-handling"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}