Repository navigation
[BUG] Desktop app: turns started by session resume or inter-session message hang with no first token, watchdog kills after ~980s (no_response) — spiked after auto-update 1.26832.0 → 1.28929.0 #86344
Description
Activity
- addedbugSomething isn't workingSomething isn't workingplatform:macosIssue specifically occurs on macOSIssue specifically occurs on macOShas reproHas detailed reproduction stepsHas detailed reproduction steps
on Aug 13, 2026 arthurmoraesfernandes-afk commented
on Aug 14, 2026 More actionsThis looks like the "wedge" mechanism documented in the follow-up comment on #86298, with app-log evidence: an injected cross-session message that the CLI holds (consent gate) gets drained into the CLI at a turn boundary and is never "echoed" back as a user turn; the app then logs
isRunning held by unechoed input at result … pendingEchoUuids: […]and treats the session as busy indefinitely — phantom turn, watchdog kills, and the user's own typed prompts queue/stall behind a turn that never ends until apriority=nextsend (typing another message force-flushes) or a restart reclaims it. The no-first-token hangs on resume/inter-session turns match the wedged state.Same failure class on macOS, engine 2.1.229 — with one piece of evidence I haven't seen in this thread yet: a thread sample of the stuck engine taken while the app claimed a turn was in flight. The engine was completely idle. The hang is in the desktop app's delivery/echo-tracking layer; the CLI process never receives the input.
Environment
- macOS Tahoe 26.5.2 (build 25F84, Darwin kernel 25.5.0), MacBook Pro M3 Pro, 18 GB
- Claude for Mac 1.30096.5 (6e1346), bundled engine
claude-code/2.1.229 - Local session, ~200-message history (1.4 MB
.jsonl), heavy inter-sessionsend_messageuse - Reproduced 5+ times in one evening on one session (plus twice on two other sessions, same night)
Direct evidence the engine never gets the message
While the UI spinner had been running ~4 minutes and a
send_messagecall returned "it will be processed after the in-flight turn finishes":/usr/bin/sample <enginePid>— main thread parked in__CFRunLoopServiceMachPort → mach_msg2_trap, event-loop thread inkevent64, HTTP client thread idle inkevent64. Zero in-flight API requests. 1548/1548 samples identical.ps: 0:05 CPU total over 4 min, 0 child processes.- Session transcript
.jsonlmtime/size frozen since engine spawn (byte-identical).
So: app says "turn in flight", engine is a parked event loop. The turn exists only in the app's state.
Two distinct drop paths in
main.logA healthy turn always logs, within ~10 s:
LocalSessions.sendMessage: sessionId=local_… Sending message to session local_… Mapping internal session local_… to CLI session <uuid> ← the delivery receiptThat
Mappingline is present for all ~40 healthy turns that night and absent in every failure.Mode A — send races the previous turn's
result(hit at 22:46, 23:06×2, 23:21×2, 00:36, 01:30):01:29:45 LocalSessions.sendMessage: … messageLength=87 01:30:15 [Stop hook] Query completed for session local_… 01:30:15 [LocalSessionManager] drained 1 deferred send(s) for local_… 01:30:15 [LocalSessionManager] isRunning held by unechoed input at result for local_… { resultUuid: '…', pendingEchoUuids: [ '…' ], nextCycleUuid: null, hasPendingCycle: true, inputStreamHasPending: false }The deferred send is flushed into the closing cycle; its echo never arrives;
isRunningis held indefinitely (observed 27+ min;CycleHealthonly firesno_responseafter the engine is externally killed). Every subsequent user message queues behind the phantom turn.Mode B — send lands during engine respawn (hit at 01:58): app logs
Resuming session/Loaded 204 transcript messages, the message renders in the UI as delivered, but nosendMessage → Mappingpair is ever logged and the transcript never grows. The UI and the transcript permanently diverge — the user believes the agent saw content it never received. This is nastier than the 2.1.228-fixed "Message sent but write failed" case because delivery is visually confirmed.Trigger profile
Matches this issue and #86557 exactly: every failure was a turn not started by a human typing in the focused window — inter-session
send_message(5×) or a send racing turn-end/idle-wake. Human-typed turns in the focused session never failed (40+/40).Workaround that recovers without data loss (except the queued messages)
kill -TERMthe specificclaude … --resume=<cliSessionId>process (find it viaps | grep resume=<cliSessionId>; map UI session → cliSessionId via~/Library/Application Support/Claude/claude-code-sessions/*/*/local_<id>.json). App logsprocess exited with code 143, releasesisRunning, respawns on next typed message with history intact. Queued/dropped messages must be re-sent manually. Leaving the session unfocused for the 15-min idle pause also clears it — but any focus resets that timer, so in practice it never self-heals while the user is watching it.Suggested defect location
LocalSessionManagerecho tracking: when a drained deferred send's input-echo races theresultevent,pendingEchoUuidsis never reconciled and there is no timeout — the log lineisRunning held by unechoed input at resultfires but nothing recovers. Separately,sendMessageduring engine respawn is acked to the UI before the stdio stream to the new process exists, so the write is lost silently. An echo-timeout (echo not seen N seconds afterresult→ replay the send or fail it visibly) would cover both modes.Update — after app restart on 1.30096.5, cross-session sends never arrive at all
After a full app restart: 4/4
send_messagedeliveries to the same session were silently dropped — including into a warm, idle, just-verified engine (it had answered a human-typed "ping" seconds earlier). Each send returned success; none ever produced theMappingreceipt; the recipient.jsonlnever contained the message. Human-typed turns in the same session remained 100% reliable throughout. On this build the feature is effectively 0% deliverable to an affected session, with false success reported to the sender every time.duplicate of #86012
Environment
Symptom
Turns that are started without a human typing in the focused window — i.e. (a) turns triggered by an inter-session message, or (b) turns that require waking a session previously paused by idle timeout — intermittently produce no first token at all. The spinner runs until the health watchdog logs:
Human-typed turns in a focused session almost always work. A Mac restart did not help; an app restart clears it only temporarily.
Measurements (from
~/Library/Logs/Claude/main.log, frozen copy, Asia/Seoul time)no_responserows across 29 sessions between Aug 12 11:16 and Aug 13 19:29. The three previous log files (Jul 30 – Aug 11, main1/2/3.log) contain 1 such row in total.Resuming sessionevents in the affected window, 19 (56%) fall within ±60s of a stall start (stall start = watchdog time minus reported duration). The older logs contain 412 resume events with at most 1 no_response row total (upper bound ≈0.2%, measured with a coarser method). The pause/resume lifecycle itself existed in older versions.Sending message to sessiondelivery within −60s/+180s of stall start. Total deliveries were ~220/day and most were processed fine — the failure is intermittent (confirmed lower bound ~10% of deliveries).[CCD start-timing]entry, so we cannot tell from the client side whether the query failed to start or the first response never arrived.Confounders we could not separate
Workaround
Pressing Esc and re-typing the prompt as a human turn recovers the session. Re-sending the inter-session message does not.
Related
Similar but not identical to #40462 (that one reports mid-turn stalls with no timeout, revived by any new message; ours never starts the turn and is killed by the watchdog).
Happy to provide sanitized log excerpts on request.