OAuth2 token fetch crashes with JSONDecodeError instead of a catchable error on rate-limit responses - #929
Open
juneja-varun wants to merge 2 commits into
Open
Conversation
Author
|
@lepture the failing tests were a real gap on my end — this repo enforces 100% diff coverage and my fix's re-raise branch (only reachable on a 2xx response with a malformed body) wasn't covered. Added a test for that case and confirmed locally: full suite passes (954 passed, 4 skipped), diff coverage is 100%, and ruff is clean. Could you approve the workflow run again when you get a chance? |
Author
|
Just following up — let me know if there's anything else needed on my end before the workflow can be re-approved. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #928.
I'm calling a token endpoint that sits behind an API gateway. When the gateway rate-limits me, it sends back a 429 with a plain-text body (completely normal gateway behavior). Instead of getting something I could catch and retry on,
fetch_token()crashed with an unhandledjson.decoder.JSONDecodeError.What's actually happening
OAuth2Client.parse_response_token()only callsresp.raise_for_status()for status codes >= 500. For anything below that, it goes straight toresp.json()- so a 4xx response with a non-JSON body (rate-limit pages, WAF blocks, HTML error pages, plain text) blows up with a rawJSONDecodeErrorinstead of a meaningful, catchable error.Reproduction
Using the exact repro from the issue (a local server returning 429 with a plain-text body):
Fix
Wrap the
resp.json()call in a try/except. On a JSON decode failure, callresp.raise_for_status()so the caller gets a properhttpx.HTTPStatusErrordescribing the actual HTTP status instead of a JSON parsing error.I deliberately didn't go with the issue's first suggested option (calling
raise_for_status()unconditionally before parsing) - that would break the normal OAuth2 error flow, where a 400 response with a well-formed{"error": "invalid_grant", ...}body is supposed to parse into a friendlyOAuthError, not an immediateHTTPStatusError. Verified this explicitly: a 400 with a valid JSON error body still raisesOAuthError(error='invalid_grant', ...)exactly as before, only the malformed-body case changes.Testing
test_fetch_token_non_json_error_responseintests/clients/test_httpx/test_oauth2_client.py, confirmed it fails on unpatched code with the exact reportedJSONDecodeErrorand passes with the fix.OAuthError).ruff checkandruff format --check: both clean.