{"record":{"id":"4246768066841fb8","repo":"thanos-io/thanos","slug":"unmarshal-query-range-response","errorCode":null,"errorMessage":"unmarshal query range response","messagePattern":"unmarshal query range response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/promclient/promclient.go","lineNumber":580,"sourceCode":"\t}\n\n\t// Decode only ResultType and load Result only as RawJson since we don't know\n\t// structure of the Result yet.\n\tvar m struct {\n\t\tData struct {\n\t\t\tResultType  string          `json:\"resultType\"`\n\t\t\tResult      json.RawMessage `json:\"result\"`\n\t\t\tExplanation *Explanation    `json:\"explanation,omitempty\"`\n\t\t} `json:\"data\"`\n\n\t\tError     string `json:\"error,omitempty\"`\n\t\tErrorType string `json:\"errorType,omitempty\"`\n\t\t// Extra fields supported by Thanos Querier.\n\t\tWarnings []string `json:\"warnings\"`\n\t}\n\n\tif err = json.Unmarshal(body, &m); err != nil {\n\t\treturn nil, nil, nil, errors.Wrap(err, \"unmarshal query range response\")\n\t}\n\n\tvar matrixResult model.Matrix\n\n\t// Decode the Result depending on the ResultType\n\tswitch m.Data.ResultType {\n\tcase string(parser.ValueTypeMatrix):\n\t\tif err = json.Unmarshal(m.Data.Result, &matrixResult); err != nil {\n\t\t\treturn nil, nil, nil, errors.Wrap(err, \"decode result into ValueTypeMatrix\")\n\t\t}\n\tdefault:\n\t\tif m.Warnings != nil {\n\t\t\treturn nil, nil, nil, errors.Errorf(\"error: %s, type: %s, warning: %s\", m.Error, m.ErrorType, strings.Join(m.Warnings, \", \"))\n\t\t}\n\t\tif m.Error != \"\" {\n\t\t\treturn nil, nil, nil, errors.Errorf(\"error: %s, type: %s\", m.Error, m.ErrorType)\n\t\t}\n","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/promclient/promclient.go#L562-L598","documentation":"QueryRange fetches /api/v1/query_range from a Prometheus/Thanos endpoint and decodes the 2xx response body into the API envelope struct (data.resultType, data.result, error, errorType, warnings). This error is wrapped around json.Unmarshal when the body is not valid JSON or its shape does not match the envelope (e.g. an HTML error page, truncated body, or a proxy response). It means the HTTP layer succeeded (status 2xx) but the payload could not be parsed as a Prometheus query_range response.","triggerScenarios":"Any call to Client.QueryRange (via Exec) where the server returns 2xx with a body that fails json.Unmarshal against the envelope struct: non-JSON body, invalid UTF-8, JSON with wrong types (e.g. data as array instead of object), or truncated/garbled response from an intermediary.","commonSituations":"Pointing Thanos Query at a non-Prometheus endpoint (UI route returning HTML behind a 200), a reverse proxy or service mesh returning an HTML/empty 200 page, TLS-terminating gateway injecting content, or compression/middleware mangling the body.","solutions":["Verify the URL points to the Prometheus/Thanos API root (e.g. https://thanos-query:9090) and not a UI or wrong path; log/print the raw response body to see what is actually returned.","Check intermediary proxies, gateways, or sidecars (ingress, envoy) that may replace the body with an HTML error page while keeping status 200.","Confirm content-encoding handling: if the server gzips the response, ensure the HTTP client transport decompresses it (DisableCompression not set incorrectly).","Reproduce with curl -v '<base>/api/v1/query_range?query=up&start=...&end=...&step=60' and inspect the body and headers."],"exampleFix":"// before: opaque failure\ncurl https://wrong-host/graph\n// after: correct API base URL\nhttps://thanos-query:9090  // /api/v1/query_range is appended by the client","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"matrix, _, _, err := client.QueryRange(ctx, u, q, st, en, step, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"unmarshal query range response\") {\n        // 2xx but non-JSON body: log body/URL, suspect proxy or wrong endpoint\n    }\n    return err\n}","preventionTips":["Point the client at a real Prometheus/Thanos API base URL, not a UI or portal","Audit proxies/gateways in the request path for body-rewriting behavior","Add a startup health check calling a cheap API endpoint and validating it parses"],"tags":["json","prometheus","http-response","unmarshal"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}