From 333f500ce46028456a476fdfaf624301cb2fcfe3 Mon Sep 17 00:00:00 2001 From: Stranmor Date: Fri, 13 Mar 2026 19:10:57 +0300 Subject: [PATCH] fix: prevent TransferEncodingError by clean SSE stream termination When SSE streams encounter upstream errors, yield Err(...) causes hyper to abort HTTP/1.1 chunked transfer encoding without the final terminator. HTTP clients (aiohttp, httpx) then throw TransferEncodingError. Fix: convert stream errors to Ok(Bytes) SSE content, matching the pattern already used by the OpenAI streaming handler. Affected: Gemini handler, Claude SSE mapper Already correct: OpenAI handler (errors wrapped as Ok) --- src-tauri/src/proxy/handlers/gemini.rs | 4 +++- src-tauri/src/proxy/mappers/claude/mod.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/proxy/handlers/gemini.rs b/src-tauri/src/proxy/handlers/gemini.rs index 9fa2c2a33..6c80d474d 100644 --- a/src-tauri/src/proxy/handlers/gemini.rs +++ b/src-tauri/src/proxy/handlers/gemini.rs @@ -343,7 +343,9 @@ pub async fn handle_generate( Some(Ok(b)) => b, Some(Err(e)) => { error!("[Gemini-SSE] Connection error: {}", e); - yield Err(format!("Stream error: {}", e)); + // Yield error as SSE content to prevent hyper aborting chunked encoding (TransferEncodingError) + let error_msg = format!("{}", e).replace('"', "'"); + yield Ok(Bytes::from(format!("data: {{\"error\":{{\"message\":\"{}\",\"type\":\"stream_error\"}}}}\n\n", error_msg))); break; } None => break, diff --git a/src-tauri/src/proxy/mappers/claude/mod.rs b/src-tauri/src/proxy/mappers/claude/mod.rs index 9ae853006..a59cc438b 100644 --- a/src-tauri/src/proxy/mappers/claude/mod.rs +++ b/src-tauri/src/proxy/mappers/claude/mod.rs @@ -82,7 +82,9 @@ where } } Err(e) => { - yield Err(format!("Stream error: {}", e)); + // Yield error as SSE content to prevent hyper aborting chunked encoding (TransferEncodingError) + let error_msg = format!("{}", e).replace('"', "'"); + yield Ok(Bytes::from(format!("event: error\ndata: {{\"error\":{{\"message\":\"{}\",\"type\":\"stream_error\"}}}}\n\n", error_msg))); break; } }