From b2c0f8dd6bf2a57cbf00ef7f4132a6bb222d7ec4 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 24 Aug 2026 23:36:53 +0200 Subject: [PATCH] Classify provider stream read failures --- src/provider_backend.rs | 48 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/provider_backend.rs b/src/provider_backend.rs index 222e58e..4553bac 100644 --- a/src/provider_backend.rs +++ b/src/provider_backend.rs @@ -500,7 +500,7 @@ fn parse_responses_sse(reader: impl Read) -> Result Result &'static str { + match kind { + io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock => "provider SSE read timed out", + io::ErrorKind::ConnectionReset + | io::ErrorKind::ConnectionAborted + | io::ErrorKind::BrokenPipe + | io::ErrorKind::NotConnected + | io::ErrorKind::UnexpectedEof => "provider SSE connection closed unexpectedly", + _ => "provider SSE read failed", + } +} + fn failed_result( invocation: &CodexTransportInvocation, failure_kind: &str, @@ -1037,6 +1049,14 @@ mod tests { use std::net::TcpListener; use std::thread; + struct FailingReader(io::ErrorKind); + + impl Read for FailingReader { + fn read(&mut self, _buffer: &mut [u8]) -> io::Result { + Err(io::Error::from(self.0)) + } + } + fn jwt(payload: Value) -> String { let payload = URL_SAFE_NO_PAD.encode(serde_json::to_vec(&payload).unwrap()); format!("e30.{payload}.signature") @@ -1213,6 +1233,32 @@ mod tests { ); } + #[test] + fn responses_stream_classifies_read_failures_without_exposing_io_details() { + for kind in [io::ErrorKind::TimedOut, io::ErrorKind::WouldBlock] { + assert_eq!( + parse_responses_sse(FailingReader(kind)).unwrap_err(), + "provider SSE read timed out" + ); + } + for kind in [ + io::ErrorKind::ConnectionReset, + io::ErrorKind::ConnectionAborted, + io::ErrorKind::BrokenPipe, + io::ErrorKind::NotConnected, + io::ErrorKind::UnexpectedEof, + ] { + assert_eq!( + parse_responses_sse(FailingReader(kind)).unwrap_err(), + "provider SSE connection closed unexpectedly" + ); + } + assert_eq!( + parse_responses_sse(FailingReader(io::ErrorKind::Other)).unwrap_err(), + "provider SSE read failed" + ); + } + #[test] fn provider_http_transmits_exact_body_and_required_identity_headers() { let listener = TcpListener::bind("127.0.0.1:0").unwrap();