Commit 6bbad5f
fix(transport): isolate stderr callback failures, continue reading lines (#932)
## Summary
Fixes #929.
`SubprocessCLITransport._handle_stderr` wrapped the entire `async for`
loop in a single `except Exception: pass`, so a raise from the
user-provided `options.stderr` callback was caught at the outer level —
the loop terminated and no further stderr lines were delivered for the
rest of the session. Silent: no log, no traceback.
The repro in #929 confirmed a callback that raises on the first line
dropped all subsequent lines (`callback_raised_count = 1` for a 2-line
stream). The contract on `stderr: Callable[[str], None]`
(`types.py:1741`) doesn't document any "must not raise" constraint, so
this is a bug, not user error.
## Changes
- `src/claude_agent_sdk/_internal/transport/subprocess_cli.py`: per-line
`try/except` around `self._options.stderr(line_str)` so a buggy callback
fails for that one line but the loop continues. The outer `except
Exception: pass` becomes `logger.debug(..., exc_info=True)` so
stream-read failures are at least visible at debug level. The `except
anyio.ClosedResourceError` for legitimate end-of-stream is preserved.
- `tests/test_transport.py`: regression test
`test_stderr_callback_raise_does_not_terminate_loop` — 3-line stream,
callback raises on line 1, asserts all 3 lines delivered.
## Test plan
- [x] `uv run pytest tests/test_transport.py` — 90 passed
- [x] `uv run mypy src/` — clean
- [x] `ruff check / ruff format` — clean
- [x] Manual repro from issue body now shows `count = 3` (was `count =
1` before fix)
Co-authored-by: Xian Zheng <xian.zheng@challenger.gauntletai.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>1 parent fc7a6de commit 6bbad5f
2 files changed
Lines changed: 43 additions & 3 deletions
Lines changed: 11 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
526 | 526 | | |
527 | 527 | | |
528 | 528 | | |
529 | | - | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
530 | 533 | | |
531 | | - | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
532 | 540 | | |
533 | 541 | | |
534 | 542 | | |
535 | | - | |
| 543 | + | |
536 | 544 | | |
537 | 545 | | |
538 | 546 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
2071 | 2072 | | |
2072 | 2073 | | |
2073 | 2074 | | |
| 2075 | + | |
| 2076 | + | |
| 2077 | + | |
| 2078 | + | |
| 2079 | + | |
| 2080 | + | |
| 2081 | + | |
| 2082 | + | |
| 2083 | + | |
| 2084 | + | |
| 2085 | + | |
| 2086 | + | |
| 2087 | + | |
| 2088 | + | |
| 2089 | + | |
| 2090 | + | |
| 2091 | + | |
| 2092 | + | |
| 2093 | + | |
| 2094 | + | |
| 2095 | + | |
| 2096 | + | |
| 2097 | + | |
| 2098 | + | |
| 2099 | + | |
| 2100 | + | |
| 2101 | + | |
| 2102 | + | |
| 2103 | + | |
| 2104 | + | |
| 2105 | + | |
2074 | 2106 | | |
2075 | 2107 | | |
2076 | 2108 | | |
| |||
0 commit comments