fix: Add graceful error handling for ChunkedEncodingError during streaming (#57)
Fixes connection interruptions from ChatGPT API by catching ChunkedEncodingError and gracefully ending the stream with [DONE] instead of returning 500 errors. Two-level error handling: 1. Catches errors during stream initialization 2. Catches errors during stream iteration This prevents abrupt failures when the upstream connection is interrupted mid-response.
This commit is contained in:
@@ -432,23 +432,46 @@ def sse_translate_chat(
|
|||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
for raw in upstream.iter_lines(decode_unicode=False):
|
try:
|
||||||
|
line_iterator = upstream.iter_lines(decode_unicode=False)
|
||||||
|
except requests.exceptions.ChunkedEncodingError as e:
|
||||||
|
if verbose and vlog:
|
||||||
|
vlog(f"Failed to start stream: {e}")
|
||||||
|
yield b"data: [DONE]\n\n"
|
||||||
|
return
|
||||||
|
|
||||||
|
for raw in line_iterator:
|
||||||
|
try:
|
||||||
if not raw:
|
if not raw:
|
||||||
continue
|
continue
|
||||||
line = raw.decode("utf-8", errors="ignore") if isinstance(raw, (bytes, bytearray)) else raw
|
line = (
|
||||||
|
raw.decode("utf-8", errors="ignore")
|
||||||
|
if isinstance(raw, (bytes, bytearray))
|
||||||
|
else raw
|
||||||
|
)
|
||||||
if verbose and vlog:
|
if verbose and vlog:
|
||||||
vlog(line)
|
vlog(line)
|
||||||
if not line.startswith("data: "):
|
if not line.startswith("data: "):
|
||||||
continue
|
continue
|
||||||
data = line[len("data: "):].strip()
|
data = line[len("data: ") :].strip()
|
||||||
if not data:
|
if not data:
|
||||||
continue
|
continue
|
||||||
if data == "[DONE]":
|
if data == "[DONE]":
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
evt = json.loads(data)
|
evt = json.loads(data)
|
||||||
except Exception:
|
except (json.JSONDecodeError, UnicodeDecodeError):
|
||||||
continue
|
continue
|
||||||
|
except (
|
||||||
|
requests.exceptions.ChunkedEncodingError,
|
||||||
|
ConnectionError,
|
||||||
|
BrokenPipeError,
|
||||||
|
) as e:
|
||||||
|
# Connection interrupted mid-stream - end gracefully
|
||||||
|
if verbose and vlog:
|
||||||
|
vlog(f"Stream interrupted: {e}")
|
||||||
|
yield b"data: [DONE]\n\n"
|
||||||
|
return
|
||||||
kind = evt.get("type")
|
kind = evt.get("type")
|
||||||
if isinstance(evt.get("response"), dict) and isinstance(evt["response"].get("id"), str):
|
if isinstance(evt.get("response"), dict) and isinstance(evt["response"].get("id"), str):
|
||||||
response_id = evt["response"].get("id") or response_id
|
response_id = evt["response"].get("id") or response_id
|
||||||
|
|||||||
Reference in New Issue
Block a user