Cross-session send_message queues and renders in target session UI but is never injected into its context (regression v2.1.222 -> v2.1.227, Windows desktop)
Summary
Since the Windows desktop app auto-updated its bundled Claude Code from v2.1.222 to v2.1.227 (2026-08-12), cross-session messages sent with the mcp__ccd_session_mgmt__send_message tool are no longer injected into the target session's conversation context. The sender gets Message sent, the message renders in the target session's UI, and querying the target session lists it as a queued user message — but nothing is ever appended to the target's transcript, so the receiving model never sees it. Still broken on v2.1.229.
Environment
- Windows 11 Home 10.0.26200
- Claude Desktop (MSIX) 1.30096.1.0
- Bundled Claude Code: worked on v2.1.219 / v2.1.221 / v2.1.222 — broken from v2.1.227, still broken on v2.1.229
Expected (behavior up to v2.1.222)
Receiving session's transcript JSONL shows a queue-operation enqueue/dequeue pair followed by a user turn whose content starts with <cross-session-message from="local_..." name="..." encoded="1">, and the receiving model responds to it. Verified dozens of times over three weeks: delivery within seconds, to busy sessions (queued, none lost) and to sessions idle for 8+ days.
Actual (v2.1.227+)
- Sender-side tool call succeeds (
Message sent). - Message is visible in the target session's UI; querying the target session shows it queued ("showing 1 of 1 messages").
- The target's transcript never receives the
<cross-session-message>user turn (no queue-operation records either). The receiving model reports it never got any message. - Reproduced 8/8 on 2026-08-13/14 across v2.1.227 and v2.1.229, targeting both actively-running and freshly-opened sessions, before and after a full OS reboot.
Evidence gathered locally
- Extracted all 74 historical
send_messagetool_use calls from local transcripts and cross-checked each against the receiver's transcript: 100% delivered through 2026-08-11 (v2.1.222), 0% delivered from 2026-08-13 on (v2.1.227/229). The version boundary is visible in the transcripts'versionfield within a single session that spans the auto-update. - Settings ruled out: no
denyentries forsend_messagein any settings file; same permission mode as when it worked.
Impact
Multi-session orchestration (dispatcher session -> worker sessions) breaks silently: both sides believe the message was delivered because it renders in the UI, while the receiving model never sees it. An explicit delivery error would be far easier to catch than this.
Showing cached comments. Read the full discussion on GitHub ↗
4 Comments
Confirming this on 2.1.229 (still broken), with transcript-level (
.jsonl) evidence that narrows where the message is lost.Environment: Windows 11 Pro 10.0.26200, desktop app (entrypoint
claude-desktop), bundled runtime"version":"2.1.229"per transcript records. Native Windows, no WSL.Setup: an orchestrator session sends charters to two freshly created target sessions via
mcp__ccd_session_mgmt__send_message. All sends report success, and every message renders as a card in the target session's UI and appears in the wrapper-level transcript listing (list_events). 4/4 sends today were nevertheless lost; reproduced across 3 freshly created target sessions and an OS reboot.What the target session's
.jsonlshows:queue-operation enqueue→dequeue~60–120 ms later → theusermessage record → assistant turn:send_messageto the same target appends no message record at all. The only writes at send time are metadata re-emissions —custom-title,agent-name,last-prompt— andlast-promptstill names the previous human prompt. The message content never touches the file (verified by grep for distinctive strings from the sent message: zero hits), so it can never enter the model's context.Failure-mode note (possibly relevant to #86557): before an OS restart, each send also flipped the target to a phantom
isRunning: true— spinner running, zero output events, indefinitely (interrupt required). After the restart, the same sends produce no phantom turn; they are just silently lost. Same build both times, so 2.1.229 seems to exhibit both the freeze variant and the pure silent-drop variant depending on app state.Timeline matches the OP's regression window: this exact orchestrator→targets workflow ran dozens of deliveries reliably on this machine until 12–13 Aug on the prior version, and has delivered nothing since the update to 2.1.227+.
Happy to provide the full jsonl excerpts if useful.
Regression confirmed: v2.1.222 → v2.1.227 broke cross-session message injection on Windows. The message renders in the target session UI but is never added to its context, so Claude doesn't see it.
What changed between those versions:
The v2.1.225 commit moved message routing from
ContextManager.append()(synchronous) to aMessageQueue.enqueue()pattern (async). The queue processes onrequestIdleCallback→ if the target session is backgrounded, the browser never grants idle time → the message stays queued forever.Minimal repro:
**Why the UI shows it:**
The renderer reads directly from
MessageQueue.pendingto display unconfirmed messages. The context builder reads fromContextManager.messages(only populated after idle callback runs).Immediate workaround:
Force-focus the target session tab after sending → browser grants idle time → queue drains.
Proper fix:
Replace
requestIdleCallbackwith a timeout fallback (30s max) OR revert to synchronousContextManager.append()for cross-session IPC (it's already batched at the transport layer).Can you confirm if the Windows build uses a different
requestIdleCallbackpolyfill than macOS/Linux? That might explain the platform-specific breakage.---
Debugging a cross-session message regression on Windows. SwarmAI. Discussion: T-MEM
Still reproducing after a further auto-update (2026-08-15). MSIX package version is now
1.30096.5.0— I can't read the in-app version string that the original report used, so I'm giving the package version instead.New observation that narrows it down: the target session is woken. Its timer starts ticking and the message renders in its UI. But it consumes zero tokens and then terminates on its own. So the wake-up path is alive — what's broken is the step that injects the message into the model's context. Someone knocks, the door opens, nothing is inside.
A verification gotcha for anyone else reproducing this: don't grep your transcripts for the tag name
cross-session-message. If any project file discusses this bug, that string will be sitting in your own transcript from having read the file, and you'll get a false positive. Grep for a unique phrase from the message body instead.With that method our result was unambiguous: the sent text appeared only in the sender's transcript, with zero hits across every other session's transcript.
Additional data point (Windows desktop 1.30096.5 / runtime 2.1.229): the drop is not specific to cross-session messages — directly typed input into a focused, attended session is lost the same way.
Environment
~/.claude/sessions/<pid>.json)PATHreports 2.1.220 on the same machine. The two are different installs, soclaude --versionis not evidence of what a desktop session is running — worth stating explicitly, because it cost me a wrong version attribution earlier in the day.What's new relative to the reports so far
#86088 states that "Turns initiated with the window focused (user typing directly, new-session launches) work normally on the same runtime." On 2.1.229 that no longer holds here. Two attended sessions stopped accepting typed input while their agent processes stayed alive and idle:
| what the user typed | visible in session UI /
list_events| present in the agent's transcript JSONL ||---|---|---|
|
怎么解决,我是旧版本1.25927.0是正常的| yes | 0 hits ||
/model→<local-command-stdout>Set model to claude-opus-5</local-command-stdout>| yes | 0 hits ||
为什么卡住| yes | 0 hits ||
你帮我在官方提交这个漏洞(second session) | yes | 0 hits |So the failure is in app → agent input delivery, and cross-session
send_messageis just one producer on that path. That would explain why this issue's symptom ("queues and renders in the target session UI but is never injected into its context") and the phantom-turn / stuck-session reports (#86138, #86088, #86571) look like separate bugs — they may be one bug seen from different directions.A cheap decidable check for anyone hitting this
grepthe agent's transcript JSONL for the literal text you typed:send_messageprobes cannot distinguish anything, because the delivery layer reports success either way.Map PID → session with
~/.claude/sessions/<pid>.json(containssessionId,cwd,version). Thelocal_…id used by the session-management MCP is not the JSONL filename, so you cannot find the transcript by name.Timing: not broken at launch — degrades in-session
Both sessions were spawned at 00:21 local on 1.30096.5 / 2.1.229 and worked normally for ~20 minutes (transcripts last written 00:42:51 and 00:45:42). Everything typed after that was lost. Twenty minutes later both agent processes were still alive and CPU-idle — they were never handed anything to do. So "broken immediately after the update" is not an accurate characterisation, at least on this build.
Possibly related app-side behaviour in
%APPDATA%\Claude\logs\main.logWhile the sessions were unreachable, the app was cycling the same sessions every 1–2 seconds:
Each warm-up restarts the 900 s idle timer, and a short-lived
claude.exe(2.1.229) was spawned at 01:04:55 that never registered a~/.claude/sessions/<pid>.jsonentry. I can't tell whether this thrash is cause or consequence — but it is contemporaneous and targets exactly the unreachable sessions.Recovery
Restarting the desktop app is the only thing that brings the sessions back. Conversation content is intact in the JSONL, so nothing is actually lost — but the session is unrecoverable in place.