Skip to content

Commit c381a63

Browse files
committed
fix(thread): narrow except in _fallback_stream from BaseException to Exception
github-code-quality caught that the stream-error capture in f4c6253 used `except BaseException`, which would swallow CancelledError, KeyboardInterrupt, SystemExit, and GeneratorExit along with the normal runtime errors we want to flush around. Narrowed to `except Exception`. Control-flow exceptions now propagate immediately; the existing `finally: stop_event.set()` still signals the background edit loop to exit cleanly on cancellation, so there's no task leak on shutdown either. https://claude.ai/code/session_01XE1bMoQ5BjCvgi1iLGKKhG
1 parent f4c6253 commit c381a63

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

src/chat_sdk/thread.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ async def _edit_loop() -> None:
637637
if msg is not None:
638638
pending_edit = asyncio.create_task(_edit_loop())
639639

640-
stream_error: BaseException | None = None
640+
stream_error: Exception | None = None
641641
try:
642642
async for chunk in text_stream:
643643
renderer.push(chunk)
@@ -648,13 +648,20 @@ async def _edit_loop() -> None:
648648
thread_id_for_edits = msg.thread_id or self._id
649649
last_edit_content = content
650650
pending_edit = asyncio.create_task(_edit_loop())
651-
except BaseException as exc:
651+
except Exception as exc:
652652
# Capture so we can run the cleanup + flush below even when the
653653
# stream raises mid-iteration (e.g. LLM connection drops). The
654654
# alternative — letting the exception propagate immediately —
655655
# would leak pending_edit as an orphan task AND strand the
656656
# placeholder as a forever-"..." message, which is exactly the
657657
# pathology the placeholder-clear divergence was added to fix.
658+
#
659+
# Control-flow exceptions (CancelledError, KeyboardInterrupt,
660+
# SystemExit, GeneratorExit) are intentionally NOT caught —
661+
# those signal shutdown and must propagate immediately.
662+
# `finally: stop_event.set()` still fires on every exit path,
663+
# so the background _edit_loop exits cleanly on cancellation
664+
# too.
658665
stream_error = exc
659666
finally:
660667
stop_event.set()

0 commit comments

Comments
 (0)