Skip to content

api: return HTTP status on non-JSON API error bodies - #2062

Open
dpacgdm wants to merge 1 commit into
prometheus:mainfrom
dpacgdm:api-check-status-before-unmarshal
Open

api: return HTTP status on non-JSON API error bodies#2062
dpacgdm wants to merge 1 commit into
prometheus:mainfrom
dpacgdm:api-check-status-before-unmarshal

Conversation

@dpacgdm

@dpacgdm dpacgdm commented Jul 21, 2026

Copy link
Copy Markdown

Summary

  • When HTTP 400/422 responses carry a non-JSON body (common via proxies), apiClientImpl.Do now returns a status-based error with the body as Detail instead of a confusing JSON unmarshal failure.
  • Existing 404/5xx paths already skipped unmarshalling; this closes the remaining gap for Prometheus API error statuses that previously tried to decode a JSON API envelope first.

Addresses #763 (status-before-unmarshal for proxy/non-JSON error bodies). Body close/exhaust is already handled by the lower HTTP client and is out of scope here.

Test plan

  • go test ./api/prometheus/v1/ -run TestAPIClientDo
  • go test ./api/prometheus/v1/ -run TestAPIs

When Prometheus API error statuses (400/422) arrive with a non-JSON body
from a proxy, prefer a status-based client error over a JSON unmarshal
failure so callers see the real HTTP code.

Signed-off-by: dpacgdm <dpac.gdm@gmail.com>

@gnanirahulnutakki gnanirahulnutakki left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reproduced one remaining status-before-decode gap: syntactically valid non-envelope JSON on HTTP 400/422 can still return a nil error. Details and a regression case are inline. The existing api/prometheus/v1 package test suite passes on the PR branch.

Comment thread api/prometheus/v1/api.go
if jsonErr := json.Unmarshal(body, &result); jsonErr != nil {
// Non-2xx API error codes (400/422) with a non-JSON body (e.g. HTML from a
// proxy) should surface the HTTP status instead of a confusing unmarshal error.
if code/100 != 2 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still allows a non-2xx response to return a nil error when the body is valid JSON but not a Prometheus API envelope. For HTTP 400 with {"message":"proxy error"}, json.Unmarshal succeeds, leaves result.Status empty, and neither status check below sets err. I reproduced this with a TestAPIClientDo case; it failed with expected error, but got none.

Could the 400/422 path also fall back to errorTypeAndMsgFor when the decoded body is not a valid API error response, with this valid-but-non-envelope JSON case added as a regression test? That would preserve issue #763's requirement that the status code is never ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants