Agent SDK bundled CLI stalls after final message: transcript has complete end_turn message, but stream-json result is never emitted

Status Open
Reported on v2.1.233
Maintainer reply None cached
Activity 0 comments · opened Aug 18, 2026

Environment

  • macOS (darwin 25.5.0, arm64)
  • @anthropic-ai/claude-agent-sdk 0.3.220 — the bundled claude-agent-sdk-darwin-arm64/claude binary is the process in question
  • Driven over ACP by @agentclientprotocol/claude-agent-acp 0.66.x (spec ^0.66.0), host is a long-lived node harness
  • Invocation (from ps): claude --output-format stream-json --verbose --input-format stream-json …
  • For version context: the standalone Claude Code CLI on the same machine is 2.1.233

What happened

A long-lived interactive session (~2.5 h, many successful turns). One turn then stalled at the very end — after the model had finished writing its answer. Timestamps UTC, 2026-08-17:

  • 03:23:31 — user turn starts
  • 03:23:33 — assistant tool_use (Bash) appears in the session transcript (~/.claude/projects/…/<session>.jsonl)
  • 03:23:49 — tool_result appears
  • 03:24:15 — assistant thinking block appears
  • 03:24:50 — final assistant text is written to the transcript: a complete message with stop_reason: "end_turn"
  • after that: no result event is ever emitted on the stream-json output; no further transcript writes, no stderr output, no exit

Process state (sampled ~25 min into the stall)

| process | state |
|---|---|
| bundled claude | alive, blocked in sleep; ~4:24 CPU consumed during the session, 0% since the stall |
| ACP adapter / host | alive, event-loop idle (uv__io_poll) |

The client's session/prompt promise therefore hangs forever (our client had no timeout of its own — we have since added a watchdog on our side).

Expected

After the final assistant message, a result event — or an error, or a process exit. Anything but indefinite silence: the transcript says the turn completed, the stream never does.

Reproducibility

One occurrence in normal use; not reproducible on demand. Happy to provide redacted transcript / status logs on request.

Workaround

Client-side stall watchdog + session/cancel escape hatch; the session itself is recoverable losslessly with claude --resume <session-id> (the transcript survives intact, including the final message that never made it onto the stream).

View original on GitHub ↗