Fix prompt hang when user message replay is absent#423
Fix prompt hang when user message replay is absent#423timvisher-dd wants to merge 1 commit intoagentclientprotocol:mainfrom
Conversation
The promptReplayed flag (87a0886) relied on seeing the user message replayed with a matching UUID before accepting a result. In practice Claude Code either doesn't replay the user message or uses a different UUID, so promptReplayed stayed false and every result was discarded as a "background task result", hanging the prompt forever. Replace promptReplayed with backgroundInitPending — a flag that detects the actual fingerprint of a background task completion: an init message immediately followed by a result with no intervening stream_event or assistant messages. Our own prompt's processing always generates stream events before the result, so the flag gets cleared and the result is accepted. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
How did you determine this? User message replay works just fine for me with the exceptions of compaction and command outputs (where we manually set it to replayed).
That's not correct. I've seen Claude emit stream events and assistant messages for background tasks. |
I took wire logs from my sessions combined with observations in my
Definitely possible I misinterpreted the results. I'll try to provide further evidence if it becomes relevant. :) |
|
I think this should be fixed on main now? |
|
I think so, yes! |
|
@timvisher-dd please retry with 0.24.1 and report back :) |
Important
Claude thinks this isn't necessary if #353 merges. I only became aware of the issue because my dev integration branch got reset to upstream/main and didn't have this replayed on top of it.
Commit 87a0886 (#400) introduced a
promptReplayedflag to distinguish background task results from the current prompt's result. The flag startsfalseand only becomestruewhen the user message is replayed through the query stream with a matching UUID.In practice, Claude Code either doesn't replay the user message or replays it with a different UUID. This causes
promptReplayedto stayfalsefor every prompt, so the result is always discarded as a "background task result". Thewhile(true)loop then blocks forever waiting for a result that will never come — hanging every prompt indefinitely.Wire logs from two independent sessions confirm:
session/promptrequest is sent"consuming background task result"— the result is discardedsession/promptrequest is ever sentFix
Replace
promptReplayedwithbackgroundInitPending— a flag that detects the actual fingerprint of a background task completion: a systeminitmessage immediately followed by aresultwith no interveningstream_eventorassistantmessages.This works because:
init → resultwith nothing in betweeninit → stream_events → result(Claude always streams its response before the result)stream_event/assistantmessages clearbackgroundInitPending, so our result is acceptedThis approach doesn't depend on user message replay at all, making it robust regardless of whether
replay-user-messagesis working correctly in the SDK.Tests added (7 new)
init+ stream events precede result without replayinit → result(no activity) correctly consumed as background task, followed by our result with stream events