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)

Status Closed — duplicate
Maintainer reply None cached
Activity 7 comments · opened Aug 14, 2026 · closed Aug 20, 2026

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_message tool_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' version field within a single session that spans the auto-update.
  • Settings ruled out: no deny entries for send_message in 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.

View original on GitHub ↗

4 Comments

batesyx · 16 days ago

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 .jsonl shows:

  1. A human-typed message to the same target appends the full expected sequence — queue-operation enqueuedequeue ~60–120 ms later → the user message record → assistant turn:
{"type":"queue-operation","operation":"enqueue","timestamp":"2026-08-14T08:00:41.405Z",...,"content":"New chat window, please hold for info"}
{"type":"queue-operation","operation":"dequeue","timestamp":"2026-08-14T08:00:41.467Z",...}
{"parentUuid":null,...,"type":"user","message":{"role":"user","content":"New chat window, please hold for in...
  1. An MCP send_message to 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 — and last-prompt still 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.
  1. Definitive context-loss proof: after two sends were visibly rendered in the target's UI, the human asked the target directly "Are you getting that message from the [orchestrator] agent or not?" The model replied: "No — nothing has come through. This is a fresh window: no agents spawned, no task notifications, no inbound messages of any kind." The rendered cards are invisible to the model.

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.

xg-gh-25 · 16 days ago

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 a MessageQueue.enqueue() pattern (async). The queue processes on requestIdleCallback → if the target session is backgrounded, the browser never grants idle time → the message stays queued forever.

Minimal repro:

// Session A sends to Session B (backgrounded tab):
IPC.send('session_B_id', { type: 'USER_MESSAGE', text: '...' });

// Session B receives and renders:
MessageQueue.enqueue(msg); // ✓ UI shows the message bubble
// BUT: requestIdleCallback never fires → context stays frozen

**Why the UI shows it:**
The renderer reads directly from MessageQueue.pending to display unconfirmed messages. The context builder reads from ContextManager.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 requestIdleCallback with a timeout fallback (30s max) OR revert to synchronous ContextManager.append() for cross-session IPC (it's already batched at the transport layer).

Can you confirm if the Windows build uses a different requestIdleCallback polyfill than macOS/Linux? That might explain the platform-specific breakage.

---
Debugging a cross-session message regression on Windows. SwarmAI. Discussion: T-MEM

NineofP9 · 16 days ago

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.

lhpnano · 15 days ago

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

  • Windows 11 Pro 10.0.26200
  • Claude Desktop 1.30096.5 (installed 2026-08-15 23:07 local)
  • Bundled Claude Code runtime 2.1.229 (from ~/.claude/sessions/<pid>.json)
  • Note: the standalone CLI on PATH reports 2.1.220 on the same machine. The two are different installs, so claude --version is 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_message is 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

grep the agent's transcript JSONL for the literal text you typed:

  • hits → the agent received it; the problem is elsewhere
  • 0 hits while the message is visible in the UI → app→agent delivery is broken. Waiting, re-sending, or firing more send_message probes cannot distinguish anything, because the delivery layer reports success either way.

Map PID → session with ~/.claude/sessions/<pid>.json (contains sessionId, cwd, version). The local_… 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.log

While the sessions were unreachable, the app was cycling the same sessions every 1–2 seconds:

01:04:55 [info] [WarmLifecycle:preview] Warming up session local_3cc777e9-...
01:04:55 [info] [CCD] LocalSessions.setFocusedSession: sessionId=local_3cc777e9-...
01:04:55 [info] LocalSessions.startShellPty: sessionId=local_3cc777e9-..., cols=80, rows=24
01:04:56 [info] [WarmLifecycle:session] Starting idle timeout for local_3cc777e9-...: 900s
01:04:56 [info] [WarmLifecycle:preview] Warming up session local_accc64d4-...
01:04:57 [info] [WarmLifecycle:preview] Warming up session local_3cc777e9-...
01:04:58 [info] [WarmLifecycle:session] Starting idle timeout for local_3cc777e9-...: 900s

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>.json entry. 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.

Showing cached comments. Read the full discussion on GitHub ↗