Remote Control (Windows desktop): disconnect crash permanently sticks the toggle; all sessions now fail with "Remote credentials fetch failed"
Summary
I drive my Windows desktop Claude Code sessions from an iPhone via Remote Control. Two defects make this unusable:
- A disconnect crash leaves the toggle permanently stuck, so a dropped session can never be re-armed — only a full app restart clears it.
- Since 2026-07-17 17:45 JST, Remote Control fails account-wide with
Remote credentials fetch failed, for every session including brand-new forks. This survived an app restart and an app update.
Everything below is copied from logs on my machine, not inference.
Environment
| | |
|---|---|
| App | Claude desktop, Windows. Reproduced on 1.21459.3.0, still failing after updating to v1.22209.0 |
| Claude Code | bundled 2.1.209; CLI on PATH 2.1.212 (auto-updating) |
| Entrypoint | CLAUDE_CODE_ENTRYPOINT=claude-desktop |
| OS | Windows 11 Pro 10.0.26200 |
| Plan | Claude Max (personal account with an auto-generated Organization) |
| Mobile | Claude iOS app |
(My orgId is available on request — omitting it here since this is a public tracker.)
---
Defect 1 — Disconnect crash leaves Remote Control permanently stuck
Observed in-session error, reproduced repeatedly:
Remote Control failed to disconnect: Cannot read properties of undefined (reading 'session_url')
Behavior: when the bridge has silently died but the session still believes it is connected, /remote-control (a toggle) attempts to disconnect first. That disconnect dereferences a session object that no longer exists and throws. The state is never cleared, so the toggle can never be turned back on. Running /remote-control again produces the identical error, indefinitely.
Consequence: the only recovery is restarting the whole app. (I had been restarting the entire PC, because re-running the command visibly does nothing but error.)
Expected: disconnect should be defensive — if the session object is already gone, treat it as already-disconnected and allow re-arming.
---
Defect 2 — Account-wide Remote credentials fetch failed (current blocker)
From %APPDATA%\Roaming\Claude\logs\main.log:
2026-07-17 17:45:52 [info] Enabling remote control for session local_ae0865eb-…
2026-07-17 17:45:57 [info] [remote-control] bridge_state: failed — Remote credentials fetch failed — see debug log
2026-07-17 17:45:57 [error] Failed to toggle remote control for local_ae0865eb-…: Remote credentials fetch failed — see debug log
2026-07-17 17:46:11 [info] Enabling remote control for session local_b97b6146-…
2026-07-17 17:46:16 [info] [remote-control] bridge_state: failed — Remote credentials fetch failed — see debug log
2026-07-17 19:47:09 [info] Enabling remote control for session local_ae0865eb-…
2026-07-17 19:47:12 [info] [remote-control] bridge_state: failed — Session creation failed — see debug log
2026-07-17 19:47:30 [info] Enabling remote control for session local_70172bf2-…
2026-07-17 19:47:35 [info] [remote-control] bridge_state: failed — Remote credentials fetch failed — see debug log
local_70172bf2-… was a freshly forked session. It failed identically — so this is not per-session state; the failure is upstream of the session.
The client-side OAuth token looks healthy at the same time:
2026-07-17 19:47:49 [info] [oauth-v2] lookup orgId=<redacted>
cacheKey=…:https://api.anthropic.com:user:inference user:file_upload user:profile user:sessions:claude_code
2026-07-17 19:47:49 [info] [oauth-v2] using cached token for orgId=<redacted>
No 401/403, no expiry, and the user:sessions:claude_code scope is present. Inference itself works fine throughout. So the failure appears specific to whatever credential the Remote Control bridge fetches.
Two distinct failure strings appear: Remote credentials fetch failed and Session creation failed.
Sub-issue: the error tells me to read a debug log that I cannot find
Both messages end with "see debug log", but main.log only contains the summary line — no underlying cause, HTTP status, or request id. There is no discoverable debug log with that detail. Please either surface that log or include the real cause in the message; as written, the instruction is a dead end for users.
---
Defect 3 — Renderer memory growth
From the app's own periodic self-report in main.log:
2026-07-17 17:45:47 [process-memory] trigger=interval tree_rss_sum=13535MB electron(14)=13535MB
top=[electron_renderer:19140:10575MB electron_renderer:5284:912MB electron_main:17648:512MB …]
A single renderer reached 10,575 MB after roughly 18 hours of uptime; the app tree totalled 13.5 GB.
After restarting the app:
2026-07-17 19:50:54 [info] [process-memory] trigger=interval tree_rss_sum=2222MB electron(12)=2222MB
top=[renderer:5184:687MB electron_main:19968:342MB …]
13.5 GB → 2.2 GB, largest renderer 680 MB. About 15 GB of system RAM was reclaimed.
Possibly relevant: my heaviest session's transcript on disk is 246 MB (~/.claude/projects/<project>/<session>.jsonl). That session involved many pasted screenshots.
---
What I have already ruled out
- Not the machine sleeping. Sleep and hibernate are fully disabled —
standby-timeoutandhibernate-timeoutare0x00000000on both AC and DC (verified viapowercfg /q SCHEME_CURRENT SUB_SLEEP). - Not
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC. It is not set. - Not stale/expired auth.
oauth-v2reportsusing cached tokenwith the correct scopes, and inference works. - Not per-session state. A brand-new forked session fails identically.
- Not fixed by restarting. Restarting the app cleared Defect 1 and the memory bloat, but
Remote credentials fetch failedpersists. - Not fixed by updating. Updating to
v1.22209.0did not help.
Impact
My primary use case is operating my desktop sessions from an iPhone while away from the machine. Two things make this fragile by design:
- Recovery requires physical access to the host. Re-arming is only possible by typing
/remote-controlon the PC — the mobile client cannot re-arm. So a drop while I'm out ends that session for the rest of the day. - Right now nothing can be armed at all, so Remote Control is completely unusable on this account.
I have moved to the Discord channel bridge (--channels plugin:discord@claude-plugins-official) as a fallback, since it does not depend on the Remote Control service. That works, but it only covers a terminal session — not the desktop app sessions I actually work in.
Requests
- Make disconnect defensive so the toggle cannot get permanently stuck (Defect 1). If the session object is already gone, treat it as disconnected rather than throwing.
- Investigate
Remote credentials fetch failed/Session creation failedfor my account (orgId available on request). The client token is healthy, so this appears to be server-side. - Surface the "debug log" the error refers to, or put the actual cause (status code / request id) into the message.
- Provide a supported way to re-arm from the mobile client, or an auto-reconnect that actually recovers. Requiring physical access defeats the purpose of the feature.
- Investigate renderer memory growth (Defect 3) — 10.5 GB in a single renderer looks like a leak, plausibly related to image-heavy transcripts.
Happy to provide
Full main.log, claude doctor output, my orgId, or any additional diagnostics on request.
3 Comments
Reproduced Defect 1 on Windows with app
1.24012.9.0/ bundled CLI2.1.219, and I think I can point at the exact lines. Everything quoted below is fromresources/app.asarand the bundledclaude.exeon my machine.1. The dereference that throws
In the session-manager's remote-control toggle:
The optional chaining is on the value (
c.session_url?.split(...)), not oncitself. Ifcisundefined, this throwsCannot read properties of undefined (reading 'session_url')— the exact string in this issue.enableRemoteControlis a thin wrapper that returns whatever the control response carries:And in the CLI's
remote_controlcontrol-request handler, the two branches are asymmetric — the enable branch answers with a payload, the disable branch answers with none:(I did not decompile
Mnitself — it is a reused minified name — so I can't say from source alone whether it emitsresponse: undefinedor an empty object. But the observed exception provescisundefinedon this path, and the missing guard oncis plain in the source.)2. Why it sticks permanently — this is the part that makes it unrecoverable
The catch block only clears the state on the enable path:
and the desired direction is derived from that same flag:
So once a bridge dies silently while
remoteControlEnabledis stilltrue:/remote-control→n = false→ disable path → throw → state not reset → next/remote-control→n = falseagain → identical throw, forever. An app restart is the only thing that clears the in-memory flag, exactly as reported.A guard on
cwould stop the exception, but the asymmetric catch is worth fixing independently — any failure on the disable path currently leaves the toggle wedged.3. What puts a session into this state: lingering background tasks
On my machine the sessions that lose Remote Control are consistently the ones with a background task still registered, and
pauseSession()explains why. It early-returns forisRunning,activeCronJobs,pendingLoopWakeupand background tasks:The affected session logged this every 15 minutes for more than five hours straight:
Sessions on the same machine without a background task were paused normally and kept working — one of them armed cleanly 20 seconds later:
So a background task pins the session unpaused indefinitely; its bridge eventually dies on its own (in my earlier logs, usually
Transport closed: … no longer the active worker for the session (code 4090), which has no reconnect path — only401and4091are retried insetOnClose); and from then on Defect 1 makes it unrecoverable without restarting the app.Workaround for anyone hitting this: don't leave long-running background tasks in a session you need to keep remote-controlling, and re-arm Remote Control after such a task finishes. Once the error appears, restarting the app is the only recovery.
Addendum: proposed fix, scoped so it can be applied as-is.
Users cannot patch this themselves — the defective code lives in the desktop app's
app.asarinside the signed MSIX package (C:\Program Files\WindowsApps\…, TrustedInstaller-owned, signature-validated) — so here is the smallest complete fix for the maintainers. Everything is in the one session-manager method quoted in my previous comment; the CLI needs no change (its disable branch already tears down the bridge and nulls its own state before responding, so after the app-side throw the CLI is clean — only the app's in-memory flags are wedged).Names below are the minified ones from
app.asarin app build1.24012.9.0;e= session record,n= desired direction,c= control response.Change 1 — don't dereference a payload that the disable path legitimately doesn't send.
The disable branch of the CLI's
remote_controlhandler answers with no payload (Mn(dt)vs the enable branch'sMn(dt, {session_url, connect_url, environment_id})), soc === undefinedis a normal disable outcome, not an error. Every downstream use in this method already toleratesundefined(lis guarded, and the disable arm of the success path only writese.remoteControlEnabled = !1etc.). Alternatively — or additionally, for defense in depth — the CLI could answerMn(dt, {})on the disable branch; either side of the contract fixed alone stops the crash, but the app-side guard also covers older CLI versions.Change 2 — make the catch reset state on the disable path too, so no failure can wedge the toggle.
Rationale: by the time the disable path can throw,
enableRemoteControl(false)has either already run (CLI tore the bridge down) or failed against a bridge that is already dead — in both cases the truthful app state is "not connected". Clearing the flags means the next/remote-controlcomputesn = !e.remoteControlEnabled = trueand takes the enable path, i.e. the toggle recovers instead of looping on disconnect forever. This is the part that turns "restart the whole app" into "just toggle again".Change 1 alone stops the exception; change 2 alone stops any future disable-path exception from wedging the toggle permanently. Both are one-line-scale and confined to this method.
Left out deliberately (separate defects, separate fixes): the bridge's missing reconnect for close code 4090 (only
401/4091reconnect insetOnClose), and the background-task pause-skip that keeps such sessions alive long enough to hit this — happy to file those separately if useful.Same here, and still reproducing on the latest versions (2026-07-31 JST).
Environment
OS Windows 11 Home, build 10.0.26200 (same build as the original report)
Claude Code (desktop app) 2.1.219
Claude Code (CLI) 2.1.220 (updated manually for this test)
Plan Claude Max (personal)
Auth Claude account / OAuth (no API key)
Symptom
Toggling Remote Control on always fails with:
Remote Control を切り替えられませんでした。もう一度お試しください。 (Couldn't toggle Remote Control. Please try again.)
Notably, the UI looks like it partially succeeded:
the toggle turns blue (ON)
a session URL is shown under "Open in browser" (e.g. https://claude.ai/code/session_01RHUJ…)
that URL actually opens in a browser
…but the toggle still reports failure, and Remote Control never works.
What I ruled out (all clean)
Plan: Max (supported)
Auth: OAuth via Claude account, ANTHROPIC_API_KEY not set
Env vars: DISABLE_TELEMETRY, DO_NOT_TRACK, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_GROWTHBOOK, ANTHROPIC_BASE_URL — none set in User or Machine scope
Managed policy: C:\ProgramData\ClaudeCode\managed-settings.json does not exist
Network: claude.ai, api.anthropic.com, statsigapi.net, featureassets.org all reachable on 443
Telemetry: no new failed-event records around the failures (client-side sending works)
claude doctor reports "No installation issues found."
Also tried (no effect)
Retrying the toggle many times
Opening the generated session URL (it opens fine)
Sign out → sign in
Restarting the app
Updating the CLI 2.1.207 → 2.1.220
Rebooting the PC
Starting a brand-new session
Extra data point: there is no CLI fallback
The docs mention /config → "Enable Remote Control for all sessions", but I could not reach that toggle from a CLI session:
Inside the desktop app's terminal panel, /config replies that the settings panel lives in the app UI, so it cannot be opened from there.
In a standalone Claude Code terminal window, typing /config was interpreted as a request and offered a settings-file skill instead of opening the Remote Control toggle.
So the only way to enable Remote Control appears to be the desktop app toggle — which always fails. There is no workaround path for desktop-app sessions.
Minor inconsistency (may or may not be related)
The session header shows Claude Max, but the local telemetry payload records "subscription_type":"pro". The two disagree inside the same client.
Error message discoverability
Same problem as reported above: the error says to retry, but nothing surfaces an HTTP status or request ID, so there is nothing actionable on the client side to diagnose further.