Windows desktop app: cross-session send_message silently fails (reports success, never delivered) after runtime 2.1.222→2.1.227 auto-update
Summary
Cross-session messaging between local sessions in the Claude Code desktop app on native Windows worked reliably before the app auto-updated its bundled runtime (2.1.222 → 2.1.227 on 2026-08-12). After the update, sending a message to another local session reports success but the message is never delivered — a silent failure with a false success signal.
Environment
- OS: Windows 11 Pro (build 10.0.26200), native (not WSL)
- Claude Code desktop app (bundled runtime auto-updated 2.1.222 → 2.1.227 on 2026-08-12)
- Separately installed CLI: 2.1.220 (not involved in repro)
- Multiple concurrent local sessions in the desktop app, same machine, same OS user
What worked before (≤ 2.1.222, desktop app)
We ran 5+ concurrent sessions coordinating a project. Session-to-session messages (the desktop app's session-management send_message) were delivered both directions for days.
What happens after the update (2.1.227)
- Session A sends a message to session B via the desktop app's session messaging.
- The tool returns success:
Message sent to session local_… ("<title>"). - Nothing ever appears in session B — confirmed by a human watching session B (not just by the sender).
- Immediately after the update there was an intermediate state where A→B deliveries still arrived but replies B→A were silently lost; after a reboot, deliveries stopped entirely while the sender still gets a success result.
No error, no held-message notice, no expiry notice on either side.
Expected
Either of:
- messages are delivered as before, or
- the send call fails loudly on an unsupported platform instead of returning success.
The docs (code.claude.com/docs/en/cross-session-messaging) state the CLI cross-session messaging feature (v2.1.224+) runs on macOS/Linux only and is not offered on native Windows. If the desktop app's session messaging on Windows was intentionally gated off by the same rollout, the regression is still the false success response — automation built on the sender's success signal breaks invisibly. A platform-unsupported error (or a "held/refused" outcome per the documented delivery model) would let clients fall back cleanly.
Impact
We coordinated a multi-session workflow (coordinator + 5 team sessions) on this channel; after the silent breakage we lost most of a morning diagnosing sessions/user error before isolating the app update as the trigger, and had to migrate coordination to file-based message passing.
Repro
- Windows 11, desktop app with runtime ≥ 2.1.224 (observed on 2.1.227).
- Open two local sessions.
- From session A, ask Claude to send a message to session B (session-management
send_message). - Observe: sender gets "Message sent…", session B never receives it.
Happy to provide timestamps or additional logs if useful.
Showing cached comments. Read the full discussion on GitHub ↗
8 Comments
Likely related / same regression family: #86012 (same environment — Windows 11 10.0.26200, desktop app, bundled CLI 2.1.227; recipient session hangs with hadFirstResponse=false after send_message injection). #86012's mechanism explains what we observed as "silent non-delivery": the recipient query stalls entirely, so from the sender's side the message appears sent-but-never-answered. Our report adds the false-success axis: the sender receives "Message sent" even when nothing is ever processed.
Reproduced independently on a second Windows 11 Pro machine (build 10.0.26200, desktop app, native, multiple local sessions, same OS user).
One additional data point that narrows it down: in our repro the message does render in the target session's transcript UI (a "Message from {sender}" card is visible to the human), but it never enters the model's context — when asked, the target session enumerates its received turns and the message is not among them, and no new turn is spawned. So delivery to the UI succeeds; injection into the model's conversation / turn-spawning is what fails. Possibly related to #61718 (queued messages delivered but not actioned).
Second independent report — different machine, different account, Windows 10.
We hit this on 2026-08-12/13 and spent about five hours misdiagnosing it before
finding this issue. Adding only what isn't already covered above.
Environment (differs from OP)
1.28929.0.0(MSIX/Appx), model Opus 5same symptom, so it is not per-machine or per-account state
Objective check that doesn't rely on asking the model
A successfully injected message appears in the recipient's transcript JSONL as a
userturn wrapping a<cross-session-message …>block. When this bug occurs,that turn is simply absent — the transcript is byte-identical to one where no
message was ever sent.
This is a cleaner signal than asking the receiving session, because it separates
"the model didn't mention it" from "the model never had it":
Restarting does not help
Worth stating explicitly, since a false-success bug often reads like stale
process state. It isn't.
Failure is bidirectional
Not just "session A can't reach session B". Verified in both directions between
the same pair within minutes of each other — each side's message card rendered in
the other's window, and neither model received anything.
queuedvssentis a red herringWhen the target is mid-turn the tool returns:
We initially believed this was the whole story (one of our sessions was genuinely
stuck in a non-terminating turn —
EscandCtrl+Cboth ineffective). It is not:messages returning plain
sentto demonstrably idle sessions were lost identically.Anyone else debugging this will probably go down that path too.
On the "return an error instead of success" request
Strongly seconding this, and it matters beyond this particular regression.
Three layers report independently, and only the last one is load-bearing:
| Layer | Signal | Actual |
|---|---|---|
| Send |
Message sent to session …| reports success || UI | Message card rendered in recipient window | visibly present |
| Context injection | no signal at all | never happens |
Because the two observable layers both say "fine", the human operator watching the
recipient's window sees the message arrive and reasonably concludes it was delivered.
That is what cost us the five hours — every intermediate hypothesis we formed
(dead session id, recipient stuck mid-turn, transient app state) was fully consistent
with everything we could observe.
Even after this regression is fixed, a success string that cannot distinguish
"handed to the UI" from "injected into the recipient's context" will make the next
delivery failure equally silent.
Workaround (same as OP, confirming it works)
Coordination moved to the shared git repo: write the message as a file, commit, push;
the recipient runs
git pulland reads it. Slower, but delivery is verifiable —the file either exists at a known commit or it does not.
Confirming this regression on Windows Desktop, with logs.
Versions
Symptom
send_messagereturns success to the sender ("Message queued for session local_…",and in a later attempt "Message sent to session local_…"), but the target session
never receives anything. No error, no retry, nothing in the target's queue.
The message IS rendered in the target session's UI window, so the user sees it
while the model never does — the assistant truthfully answers "no task arrived"
and looks like it is ignoring instructions. That mismatch is what makes this
expensive: we lost ~2 hours across three sessions before suspecting the tool.
Evidence
Last successful delivery: 2026-08-12 13:57 local (dozens of deliveries worked fine
that day and the day before, including one after a 10-hour idle gap).
After the update: zero deliveries across three freshly created sessions.
Each target's transcript queue contains only messages typed by the human:
grep '"operation":"enqueue"' <cli-session-id>.jsonl
→ only human-typed entries, no <cross-session-message …> entries
Controlled test on a completely fresh system:
14:34:26 Windows reboot (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
14:36:48 [updater] app start
14:37:03 new session created (target)
14:37:45 main.log: "Sending message to session local_<target>"
→ target queue still contains only its own opening message. Not delivered.
So the app-side dispatch is logged, but the message never reaches the CLI session.
Related warning seen earlier in main.log for another target session:
[warn] [LocalSessionManager] reaped 1 stale pendingEchoUuids for local_<id>
— CLI dropped the isReplay echo
Ruled out
was demonstrably awake, actively chatting with the user, also received nothing)
Impact
Any multi-session workflow that hands work between a planning session and an
execution session is silently broken, and the failure mode actively misleads the
user: the sender is told it worked, the human sees the message in the UI, only the
receiving model never gets it.
Suggested minimum fix
Make the success return value depend on the message actually being enqueued in the
target session, and surface a hard error otherwise — same direction as the 2.1.224
fix, which this regression appears to undo.
Confirming this on Windows with additional data points, including one that may help narrow the cause: send_message returns success even when the target session ID doesn't exist.
Environment
Claude Desktop 1.28929.0 (d1a6bc), 2026-08-11 build, Windows Server VM
32 GB RAM / 8 logical processors (AMD EPYC 9274F host) — failures occur at ~6% CPU / 14% RAM, so not resource-related
2–3 concurrent Code-tab sessions, same cwd, communicating via ccd_session_mgmt (a Reviewer/Doer code-review workflow that ran ~80 work units cleanly before this regression)
Opus 5, high effort
Loss rate: In one session, the sending agent tracked its own sends: 3 of 4 lost — send returned Message sent (or queued), recipient's transcript (checked directly by the recipient session enumerating its own history) contained nothing. The two load-bearing sends (a work plan and a plan-request) were among the lost.
No addressee validation: A send to a non-existent session ID also returned sent. One of our sessions had inferred its own ID from its transcript-file UUID (which differs from the session-management ID — list_sessions excludes self, so self-ID is guessable-wrong); peers sending to that wrong ID got success results. So sent appears to mean "the call returned," not "a recipient exists," which may be the same underlying cause as silent drops to valid-but-idle sessions.
Correlated hangs: Sessions composing large multi-paragraph send_message payloads (plans, reviews) wedge mid-turn — spinner active, no output, input queues, 8–28 minutes until "Claude Code stopped responding." Two Doer sessions wedged simultaneously, both mid-send. Short sends mostly survive. This matches #86012's recipient-side description; we see it on the sender side too.
Timeline fits the regression window: this workflow was reliable until roughly the 1.28929.0 / runtime 2.1.22x update period. Happy to provide AppData logs from ~12 incidents across Aug 12–13 if useful.
Confirming: 2.1.228 does NOT fix this. Clean A/B test below.
Another Windows/MSIX data point, but the new part is the version: I upgraded the CLI to the official 2.1.228 and the failure reproduces exactly. Reverting to 2.1.222 restores delivery within the same minute.
Clean A/B test — only variable changed is the CLI binary
Same target session, same session state (restored after app restart, no activity since), same machine, same sender, same message shape. Nothing else touched between the two runs.
| | CLI 2.1.228 | CLI 2.1.222 |
|---|---|---|
| Target session | same session | same session |
| Target state | restored after restart, not activated since | identical |
|
send_messagereturn |sent|sent|| Receiver
.jsonlafter send | 150 s watch:33479 -> 33479bytes — zero growth | landed immediately (elapsed 0.0s, ts2026-08-14T07:41:21.051) || Receiver actually replied | no | yes |
I also tested two other targets under 2.1.228 — one with a 4.5 MB context and one freshly created after the upgrade and active seconds before the send. All three: zero bytes of growth. So it is not "the receiver is just slow" and not "only restored sessions are affected" (the freshly created one failed too).
Important diagnostic difference: the 2.1.227 log marker does not appear on 2.1.228
On 2.1.227 the failure is accompanied by:
On 2.1.228 this string never appears. In my
main.logit stayed at 22 occurrences, last one2026-08-13 21:32:49, i.e. zero new occurrences under 2.1.228 while delivery was fully broken.Instead, under 2.1.228 there is no delivery activity logged at all. Under 2.1.222 every send produces:
Under 2.1.228, nothing — not even an attempt.
Binaries (so this is reproducible / verifiable)
Both hashes verified before and after each swap. After the upgrade, the
versionfield inside my own session.jsonlread2.1.228— so the process really was running the new binary, not a stale one.Environment
[CCD-autoupdate] Disabled: MSIX installon every launch — the CLI version is pinned by the desktop app, it does not self-updateThe only landing criterion I found trustworthy
Four signals all report success while nothing is delivered:
send_messagereturn value (sentandqueuedboth lie)list_events— the message is visible in the UI storedrained N deferred send(s)inmain.logflushed held steerscountsThe only reliable check is the receiver's transcript on disk:
⚠️ One trap that will make you misread a healthy channel as broken: an in-flight turn is not flushed to disk. The
userrecord that triggered a turn is only written after that turn ends. So the receiver can never observe its own inbound record within the turn that is processing it — ask a third party to read the receiver's transcript instead, or wait for the turn to finish. I lost time to this before realising the channel was fine at that moment.Suggested triage note
Given 222 works and both 227 and 228 fail — and the issue body states the feature was introduced in 2.1.224+ — it would help a lot to know whether 2.1.224 / 225 / 226 are affected, and whether the fix shipped in 2.1.228 (described as applying to "the first session after install or upgrade") was ever intended to cover the case here, which is all sessions, indefinitely, not just the first one after upgrade.
Happy to run further tests on this machine — I have both binaries staged and can swap them in a couple of minutes.
Update after upgrading to desktop 1.30096.0.0 / runtime 2.1.229: the false-success axis reported here appears fixed — sends now deliver and render in the recipient session (2.1.228 changelog fix confirmed working). However the recipient session then hangs with zero output (#86012), reproduced on 2.1.229. Closing the loop: our original 'silent non-delivery' was likely #86012's hang observed from the sender side. This issue's remaining value is the platform question (docs still say native Windows unsupported, yet delivery now works there).
Same regression window and signature — #86298 documents the same failure chain with root-cause analysis (Windows desktop, regression at app 1.28929.0 / bundled CLI 2.1.227, still present on app 1.30096.1.0 / CLI 2.1.229): the desktop bridge sends the message with a class-less
origin:{kind:'peer'}, the recipient CLI/SDK's cross-session consent gate holds it for an approval no desktop surface offers, anddialogExpiry(~5 min) then drops it — while the sender keeps a success receipt. A memory-dump repro in that thread shows the payload reaching the recipient CLI process but never its transcript. SettingcrossSessionInbound: "accept"in user settings does not unblock it (tested on running, cold-started, and post-restart fresh sessions).