From 7b6e9af23af7e12f4fdefc3366c4c6b0d8a3dcf7 Mon Sep 17 00:00:00 2001 From: anish Date: Mon, 20 Jul 2026 05:51:56 +0000 Subject: [PATCH] fix(transport): handle clean process exit in read_messages to trigger teardown The read_messages function in subprocess_cli.py only raised ProcessError when the CLI process exited with a nonzero returncode. This left the clean exit case (returncode=0) unhandled, meaning read_messages would return silently without signaling that the CLI had terminated. The caller had no explicit indication that the process had exited, preventing proper cleanup and teardown. Signed-off-by: anish --- .../_internal/transport/subprocess_cli.py | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/claude_agent_sdk/_internal/transport/subprocess_cli.py b/src/claude_agent_sdk/_internal/transport/subprocess_cli.py index faaec2d5..e2e3da23 100644 --- a/src/claude_agent_sdk/_internal/transport/subprocess_cli.py +++ b/src/claude_agent_sdk/_internal/transport/subprocess_cli.py @@ -813,19 +813,29 @@ def guard(length: int) -> None: if data is not None: yield data - # Check process completion and handle errors + # Check process completion and handle both clean and error exits. + # Explicitly handling clean exit (returncode==0) ensures read_messages + # unblocks promptly when the CLI terminates, triggering proper teardown + # in the caller regardless of exit status. try: returncode = await self._process.wait() except Exception: returncode = -1 - # Use exit code for error detection - if returncode is not None and returncode != 0: - self._exit_error = ProcessError( - f"Command failed with exit code {returncode}", - exit_code=returncode, - stderr="Check stderr output for details", - ) + # Raise ProcessError for any process termination to signal the caller + if returncode is not None: + if returncode == 0: + self._exit_error = ProcessError( + "CLI process exited", + exit_code=returncode, + stderr=None, + ) + else: + self._exit_error = ProcessError( + f"Command failed with exit code {returncode}", + exit_code=returncode, + stderr="Check stderr output for details", + ) raise self._exit_error async def _check_claude_version(self) -> None: