fix: don't crash reading a non-JSON body from the IDP (FLYTE-SDK-60) - #1453
Open
EngHabu wants to merge 1 commit into
Open
fix: don't crash reading a non-JSON body from the IDP (FLYTE-SDK-60)#1453EngHabu wants to merge 1 commit into
EngHabu wants to merge 1 commit into
Conversation
The OAuth token and device-code endpoints are specified to answer in JSON, but what reaches the SDK is whatever a deployment puts in the way: a load balancer's HTML 502 page, a proxy's plain-text "Internal Server Error", an SSO interstitial. Four `response.json()` calls read those bodies unguarded, and two of them sit on the *error* paths -- so the SDK crashed with a bare `json.JSONDecodeError` on its way to raising the well-formed `AuthenticationError` it already had ready. Because the decode error is not a classified auth failure, it survives the SelectCluster/upload wrap unrecognized and lands in Sentry as an SDK bug, with `Expecting value: line 1 column 1 (char 0)` as the only thing the user is told. Parse the body defensively and let each branch report what actually came back. fixes FLYTE-SDK-60 Signed-off-by: Haytham Abuelfutuh <haytham@afutuh.com>
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.
The bug
get_tokenreads the failure body as JSON before raising the error it already has ready:The OAuth endpoints are specified to answer in JSON, but what actually reaches the SDK is whatever a deployment puts in the way. The FLYTE-SDK-60 event is a proxy answering
Internal Server Errorin front of a broken IDP, so.json()raises and theAuthenticationErroron the next line never happens.There are four unguarded
.json()calls betweenget_tokenandget_device_code, and two of them are on error paths — including one interpolated into the message of the exception being constructed:Why it reaches Sentry
json.JSONDecodeErroris not a classified auth failure, so it survives the wrap chain unrecognized:_sentry._is_user_erroralready walks the cause chain looking forAuthenticationErrorbehind exactly thisSelectClusterwrap — the comment there says so. It just never finds one, because the classification was lost at the first frame. So the user is toldExpecting value: line 1 column 1 (char 0)and we get a crash report for someone else's 502.The fix
Parse defensively and let each branch report what came back. No branch changes what it raises — they just survive reading the body first.
_json_object_or_nonereturnsNoneinstead of raising, and only accepts a JSON object: a body parsing to the bare string"error"would satisfy"error" in jby substring, which isn't the membership test the caller means._body_snippetnames the content-type and a truncated body, so "the endpoint isn't the IDP" is legible without dumping a 5KB HTML page into a log line.access_token— same branch, andKeyError: 'access_token'is the same unactionable crash report as the decode error.Verification
The test module imports new symbols, so stashing
src/would fail at collection and prove nothing. Verified with a standalone repro instead:And through the real wrap chain from the Sentry event, confirming the report actually stops:
Tests
20 cases in
tests/flyte/remote/test_token_client.py— the four non-JSON bodies, the JSON-but-not-an-object cases, snippet truncation, and the happy paths that must keep working (access token returned, absent refresh token, and theauthorization_pending/slow_downbranch that keeps the device-code poll loop alive).tests/flyte/remote/is 595 passed;make check-docstrings,ruff, andmypyclean.Not in scope
j["expires_in"]on the success path can stillKeyError— RFC 6749 makesexpires_inRECOMMENDED, not required, so a conforming IDP may omit it. Picking a default there changes refresh timing, which is a judgment call rather than a crash fix, and there's no Sentry evidence for it. Happy to follow up if you want a value chosen.fixes FLYTE-SDK-60