diff --git a/graph/fixes/rust-reqwest-responsejson-yields-reqwesterror-not-serde-json-27a1f7.md b/graph/fixes/rust-reqwest-responsejson-yields-reqwesterror-not-serde-json-27a1f7.md new file mode 100644 index 00000000000..7a2bbc35ea1 --- /dev/null +++ b/graph/fixes/rust-reqwest-responsejson-yields-reqwesterror-not-serde-json-27a1f7.md @@ -0,0 +1,44 @@ +--- +id: 27a1f728-ec90-469c-a6ab-5644d333322f +type: fix +title: "Rust: reqwest response.json() yields reqwest::Error, not serde_json::Error" +tags: [rust, reqwest, serde, error-handling, serde_json, api] +importance: 0.5 +confidence: 0.8 +created: "2026-02-28T04:58:15.771467+00:00" +updated: "2026-02-28T04:58:15.771467+00:00" +--- + +# Fix: reqwest JSON Error Type Mismatch + +## Problem + +When using `response.json::().await`, JSON decode failures produce a `reqwest::Error` — not a `serde_json::Error`. This means a custom error variant like: + +```rust +#[derive(Debug, thiserror::Error)] +enum ApiError { + #[error("Parse error: {0}")] + Parse(#[from] serde_json::Error), + // ... +} +``` + +...is **unreachable** if you only call `response.json()`. The `#[from]` impl exists but can never fire. + +## Fix + +Decode manually in two steps so the `serde_json::Error` is produced directly: + +```rust +let body = response.text().await.map_err(ApiError::Request)?; +let data = serde_json::from_str::(&body).map_err(ApiError::Parse)?; +``` + +## Why It Matters + +This lets callers distinguish **network errors** (connection dropped, timeout) from **JSON parse errors** (malformed response, schema mismatch). With `response.json()`, both collapse into `reqwest::Error` and you lose that distinction. + +## Context + +Caught during code review of `api/client.rs` in SBA Scout Rust rewrite Phase 2.