From 2fc50add8a3f8753a200501e57bdc7c5c0400540 Mon Sep 17 00:00:00 2001 From: Eddie A Tejeda <669988+eddietejeda@users.noreply.github.com> Date: Mon, 20 Jul 2026 09:11:56 -0700 Subject: [PATCH] fix(errors): never print a blank error for an empty response body MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under heavy load a small fraction of requests (~0.02-0.06%) failed with an error line that was nothing but ANSI color codes: a dropped connection or bodyless 5xx produced an empty body, api_error() echoed it verbatim, and print paths rendered red("") — invisible output with exit 1. - util::api_error: empty/whitespace body now falls back to 'unexpected empty response from server' (covers every caller, including the direct api_error(...).red() prints in databases.rs). - sdk::format_fail_message: when the body is empty the HTTP status is the only signal there is, so surface it: 'error: HTTP 502 Bad Gateway (empty response body)'. --- src/client/sdk.rs | 17 +++++++++++++++++ src/util.rs | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/client/sdk.rs b/src/client/sdk.rs index 9cf931b..6a61380 100644 --- a/src/client/sdk.rs +++ b/src/client/sdk.rs @@ -894,6 +894,11 @@ pub fn format_fail_message( util::api_error(body.to_string()) ); } + // An empty body carries no explanation of its own — the status line is + // the only signal there is, so surface it instead of a blank message. + if body.trim().is_empty() { + return format!("error: HTTP {status} (empty response body)"); + } util::api_error(body.to_string()) } @@ -973,6 +978,18 @@ mod tests { assert_eq!(msg, "server exploded"); } + #[test] + fn format_fail_message_empty_body_surfaces_status() { + // An empty response body used to fall through to a blank message + // (an error line that was only ANSI color codes). The HTTP status is + // the only signal available, so it must appear. + let msg = format_fail_message(reqwest::StatusCode::BAD_GATEWAY, "", None); + assert_eq!(msg, "error: HTTP 502 Bad Gateway (empty response body)"); + + let msg = format_fail_message(reqwest::StatusCode::SERVICE_UNAVAILABLE, " \n", None); + assert!(msg.contains("503"), "got: {msg}"); + } + #[test] fn format_fail_message_4xx_connection_error_on_probe_falls_through() { let body = r#"{"error":{"message":"forbidden"}}"#; diff --git a/src/util.rs b/src/util.rs index 8c0a0e8..1f21d59 100644 --- a/src/util.rs +++ b/src/util.rs @@ -377,6 +377,11 @@ pub fn api_error(body: String) -> String { if body.trim_start().starts_with('<') { return "unexpected server error".to_string(); } + // A dropped connection or bodyless 5xx yields an empty body; returning it + // verbatim would print as a blank (color-codes-only) error line. + if body.trim().is_empty() { + return "unexpected empty response from server".to_string(); + } body } @@ -459,6 +464,20 @@ mod tests { assert_eq!(api_error(body), "unexpected server error"); } + #[test] + fn api_error_never_returns_blank_for_empty_body() { + // A dropped connection or bodyless 5xx used to echo the empty body, + // printing an error line that was nothing but color codes. + assert_eq!( + api_error(String::new()), + "unexpected empty response from server" + ); + assert_eq!( + api_error(" \n".to_string()), + "unexpected empty response from server" + ); + } + #[test] fn is_access_denied_detects_code() { assert!(is_access_denied(