Skip to content

Report what serde objected to when a response will not parse - #82

Merged
sionsmith merged 2 commits into
osodevops:mainfrom
aberoham:fix/graph-error-detail
Aug 29, 2026
Merged

Report what serde objected to when a response will not parse#82
sionsmith merged 2 commits into
osodevops:mainfrom
aberoham:fix/graph-error-detail

Conversation

@aberoham

Copy link
Copy Markdown
Contributor

A response Graph considers successful but this crate cannot deserialize was
reported as:

API error (200): Failed to parse API response: error decoding response body

That names neither the offending value nor where it sat, so the only way to
investigate one was to capture the response by hand. It is how #69 came to
need a live account to find a one-word type error.

reqwest::Error keeps serde's account of the mismatch one level down its
source chain and Display never reaches it. describe_with_causes walks the
chain, and the same failure now reads:

API error (200): Failed to parse API response: error decoding response body: invalid type: map, expected a string at line 1 column 66

Scope

Six call sites report a parse failure to the user and all six lost it the same
way: the Graph client, which covers every response the CLI deserializes, and
the five token-exchange paths across the three login flows — including both
device-code decoders, which are easy to miss because they call .json() with
the type on the binding rather than the call.

keyring.rs is left alone: it parses with serde_json directly, whose own
Display already carries the detail.

A cause that the outer error already quotes in full is not appended twice,
which is the common shape of a hand-written wrapper such as
write!(f, "reading config: {}", self.0).

Not done

serde_path_to_error would name the field path rather than a byte offset.
That is a dependency added for error text alone, and the type mismatch plus
the offset is already enough to act on.

Tests

A wiremock test drives a Graph-shaped mismatch through GraphClient::get and
asserts the message carries serde's objection. A second drives a malformed
token response through refresh_access_token, so the auth paths are covered
by more than the client test. Reverting either call site fails its own test.
Two unit tests cover the chain walk itself, including the no-duplication case.

Fixes #79

🤖 Generated with Claude Code

https://claude.ai/code/session_01C736oc7CeNtRZmAJrXm8sG

aberoham and others added 2 commits August 29, 2026 18:24
A response Graph considers successful but this crate cannot deserialize was
reported as `Failed to parse API response: error decoding response body`,
which names neither the offending value nor where it sat. `reqwest::Error`
keeps serde's account of the mismatch one level down its source chain and
`Display` never reaches it, so the only way to diagnose a schema drift was to
capture the response by hand — which is how osodevops#69 came to need a live account
to find a one-word type error.

`describe_with_causes` walks the chain, and the six sites that report a parse
failure to the user now use it: the Graph client, which covers every response
the CLI deserializes, and the five token-exchange paths across the three login
flows. The same message now reads `... : invalid type: map, expected a string
at line 1 column 66`.

`keyring.rs` is left alone: it parses with serde_json directly, whose own
`Display` already carries the detail.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C736oc7CeNtRZmAJrXm8sG
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqBTdhSRTBabYv7kkEiUkE
@sionsmith
sionsmith force-pushed the fix/graph-error-detail branch from 0d14266 to aac0fe3 Compare August 29, 2026 17:25
@sionsmith
sionsmith merged commit a1737eb into osodevops:main Aug 29, 2026
6 checks passed
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.

A response that will not deserialize reports only "error decoding response body"

2 participants