Skip to content

Commit 2fc50ad

Browse files
committed
fix(errors): never print a blank error for an empty response body
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)'.
1 parent b231f85 commit 2fc50ad

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

‎src/client/sdk.rs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,11 @@ pub fn format_fail_message(
894894
util::api_error(body.to_string())
895895
);
896896
}
897+
// An empty body carries no explanation of its own — the status line is
898+
// the only signal there is, so surface it instead of a blank message.
899+
if body.trim().is_empty() {
900+
return format!("error: HTTP {status} (empty response body)");
901+
}
897902
util::api_error(body.to_string())
898903
}
899904

@@ -973,6 +978,18 @@ mod tests {
973978
assert_eq!(msg, "server exploded");
974979
}
975980

981+
#[test]
982+
fn format_fail_message_empty_body_surfaces_status() {
983+
// An empty response body used to fall through to a blank message
984+
// (an error line that was only ANSI color codes). The HTTP status is
985+
// the only signal available, so it must appear.
986+
let msg = format_fail_message(reqwest::StatusCode::BAD_GATEWAY, "", None);
987+
assert_eq!(msg, "error: HTTP 502 Bad Gateway (empty response body)");
988+
989+
let msg = format_fail_message(reqwest::StatusCode::SERVICE_UNAVAILABLE, " \n", None);
990+
assert!(msg.contains("503"), "got: {msg}");
991+
}
992+
976993
#[test]
977994
fn format_fail_message_4xx_connection_error_on_probe_falls_through() {
978995
let body = r#"{"error":{"message":"forbidden"}}"#;

‎src/util.rs‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ pub fn api_error(body: String) -> String {
377377
if body.trim_start().starts_with('<') {
378378
return "unexpected server error".to_string();
379379
}
380+
// A dropped connection or bodyless 5xx yields an empty body; returning it
381+
// verbatim would print as a blank (color-codes-only) error line.
382+
if body.trim().is_empty() {
383+
return "unexpected empty response from server".to_string();
384+
}
380385
body
381386
}
382387

@@ -459,6 +464,20 @@ mod tests {
459464
assert_eq!(api_error(body), "unexpected server error");
460465
}
461466

467+
#[test]
468+
fn api_error_never_returns_blank_for_empty_body() {
469+
// A dropped connection or bodyless 5xx used to echo the empty body,
470+
// printing an error line that was nothing but color codes.
471+
assert_eq!(
472+
api_error(String::new()),
473+
"unexpected empty response from server"
474+
);
475+
assert_eq!(
476+
api_error(" \n".to_string()),
477+
"unexpected empty response from server"
478+
);
479+
}
480+
462481
#[test]
463482
fn is_access_denied_detects_code() {
464483
assert!(is_access_denied(

0 commit comments

Comments
 (0)