From 35cd09a9f7eb3020e9412debfad229b8a36024e9 Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Sat, 6 Jun 2026 01:54:36 -0700 Subject: [PATCH] fix(tui): classify stream decode failures as network errors Classify stream/body decode failures such as the #2847 report as recoverable network interruptions and add focused taxonomy coverage.\n\nVerification:\n- cargo test -p codewhale-tui error_taxonomy::tests --locked\n- git diff --check\n- cmp -s CHANGELOG.md crates/tui/CHANGELOG.md\n- ./scripts/release/check-versions.sh\n- ./scripts/release/check-ohos-deps.sh --- CHANGELOG.md | 5 +++++ crates/tui/CHANGELOG.md | 5 +++++ crates/tui/src/error_taxonomy.rs | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dae84d12..97ebb7d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -310,6 +310,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Stream/body decode failures such as `Stream read error: error decoding + response body` are now classified as recoverable network interruptions + instead of generic internal errors, keeping the transcript and triage metadata + aligned with the existing stream retry path (#2847). Thanks + @qamranmushtaq-collab for the Windows/npx DeepSeek report. - The TUI footer, `/status`, `/mcp` manager, and command-palette MCP entries now count trusted workspace-local `.codewhale/mcp.json` servers together with the global MCP config, matching `codewhale mcp list` for merged global + diff --git a/crates/tui/CHANGELOG.md b/crates/tui/CHANGELOG.md index dae84d12..97ebb7d0 100644 --- a/crates/tui/CHANGELOG.md +++ b/crates/tui/CHANGELOG.md @@ -310,6 +310,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Stream/body decode failures such as `Stream read error: error decoding + response body` are now classified as recoverable network interruptions + instead of generic internal errors, keeping the transcript and triage metadata + aligned with the existing stream retry path (#2847). Thanks + @qamranmushtaq-collab for the Windows/npx DeepSeek report. - The TUI footer, `/status`, `/mcp` manager, and command-palette MCP entries now count trusted workspace-local `.codewhale/mcp.json` servers together with the global MCP config, matching `codewhale mcp list` for merged global + diff --git a/crates/tui/src/error_taxonomy.rs b/crates/tui/src/error_taxonomy.rs index be032dd3..503b0912 100644 --- a/crates/tui/src/error_taxonomy.rs +++ b/crates/tui/src/error_taxonomy.rs @@ -342,6 +342,10 @@ pub fn classify_error_message(message: &str) -> ErrorCategory { if lower.contains("network") || lower.contains("connection") || lower.contains("dns") + || lower.contains("stream read error") + || lower.contains("error decoding response body") + || lower.contains("chunk decode error") + || lower.contains("body decode") || lower.contains("temporarily unavailable") || lower.contains(" 502 ") || lower.contains(" 503 ") @@ -548,6 +552,22 @@ mod tests { ); } + #[test] + fn network_catches_stream_body_decode_failures() { + for msg in [ + "Warn Stream read error: error decoding response body", + "Stream read error: error decoding response body", + "chunk decode error", + "provider body decode failed mid-stream", + ] { + assert_eq!( + classify(msg), + ErrorCategory::Network, + "expected Network for `{msg}`", + ); + } + } + #[test] fn authentication_beats_authorization_when_api_key_phrasing_is_used() { // "api key" landing on Authentication (not Authorization) keeps