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(