Skip to content

Commit 5808f22

Browse files
committed
review: reset _got_error_result when a new user turn is observed
A ProcessError after a prior turn's error result followed by a new user message (turn N+1 begins, then crashes before its own result) should propagate, not be suppressed by the stale flag from turn N.
1 parent a3364fc commit 5808f22

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

src/claude_agent_sdk/_internal/query.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ async def _read_messages(self) -> None:
297297
await self._transcript_mirror_batcher.flush()
298298
self._first_result_event.set()
299299
self._got_error_result = bool(message.get("is_error"))
300+
elif msg_type == "user":
301+
# New turn observed — a ProcessError now is a fresh crash,
302+
# not the expected exit from a prior error result.
303+
self._got_error_result = False
300304

301305
# Regular SDK messages go to the stream
302306
await self._message_send.send(message)

tests/test_query.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,46 @@ async def _test():
11021102

11031103
anyio.run(_test)
11041104

1105+
def test_process_error_after_error_result_then_new_turn_still_raises(self):
1106+
"""A new user turn invalidates the 'expecting imminent exit' state from
1107+
a prior turn's error result; a crash mid-new-turn must propagate."""
1108+
1109+
async def _test():
1110+
transport = self._make_transport_then_raise(
1111+
messages=[
1112+
{
1113+
"type": "result",
1114+
"subtype": "error_during_execution",
1115+
"is_error": True,
1116+
"num_turns": 1,
1117+
"session_id": "s",
1118+
"duration_ms": 1,
1119+
"duration_api_ms": 1,
1120+
"total_cost_usd": 0.0,
1121+
},
1122+
{
1123+
"type": "user",
1124+
"message": {"role": "user", "content": "next turn"},
1125+
"session_id": "s",
1126+
},
1127+
],
1128+
exc=ProcessError(
1129+
"Command failed with exit code 1", exit_code=1, stderr=""
1130+
),
1131+
)
1132+
q = Query(transport=transport, is_streaming_mode=True)
1133+
await q.start()
1134+
1135+
received = []
1136+
with pytest.raises(Exception, match="Command failed"):
1137+
async for msg in q.receive_messages():
1138+
received.append(msg)
1139+
await q.close()
1140+
1141+
assert len(received) == 2
1142+
1143+
anyio.run(_test)
1144+
11051145
def test_pending_control_requests_fail_fast_on_suppressed_exit(self):
11061146
"""Even when the ProcessError is suppressed for the message stream,
11071147
in-flight control requests must still fail fast (process is dead;

0 commit comments

Comments
 (0)