Remote control: sessions die permanently on session-limit hit and on transient disconnects; mobile app still shows them alive and silently drops messages
Summary
Two compounding defects make remote-control sessions die permanently and silently. The mobile app keeps listing them as alive, so messages sent to them are accepted by the UI and never answered.
Environment: Claude Code 2.1.212, macOS 25.5.0 (Darwin), remote-control via mobile app.
---
Defect 1 — sessions never resume after a session limit resets
On 2026-07-22 at 15:22:40 (+03), three concurrently active remote-control sessions all received:
You've hit your session limit · resets 10:30pm (Asia/Riyadh)
The limit window reset at 22:30. At 23:30 — one full hour after reset — all three sessions were still dead, with zero activity since 15:24. Nothing re-arms them. The limit is temporary; the session death is permanent.
Two aggravating details:
- The limit notice is written into the transcript as an assistant message. From the mobile app this renders as the conversation having replied, so there is no visible signal that the session is now a dead end. A user message sent at 15:23:25 got only this banner back.
- Background task notifications kept being delivered into the dead sessions (e.g. 15:25:50) and each one re-emitted the same banner — scheduled/background work continues firing into a session that can no longer act.
Defect 2 — a transient network blip tears down all active sessions
Separately, a recoverable disconnect causes claude remote-control to back off exponentially and then shut down every active session — failing even to stop them cleanly, because the network is down by definition:
·|· Reconnecting · retrying in 2.2s · disconnected 1s
·/· Reconnecting · retrying in 3.8s · disconnected 3s
[18:26:00] Shutting down 5 active session(s)…
[18:26:03] Error: Failed to stop work cse_<redacted> after 3 attempts:
getaddrinfo ENOTFOUND api.anthropic.com
Measured across ~2 days of ~/.local/state/remote-control/child.log: 5 teardown events killing 14 sessions total (1 + 5 + 1 + 3 + 4). Some disconnects were as short as 48 seconds.
The two defects compound: the three sessions killed by the limit at 15:22 were then formally torn down by this path at 18:26.
Impact
From the phone, a conversation looks alive and accepts input, but nothing is listening. There is no error, no notification, and no indication that the session is unrecoverable. Long-running delegated work is lost silently.
This is very likely the same root cause as #79827 (duplicate device registrations / stale environments) — those stale environments are the residue of these uncleaned teardowns.
Requested behavior
- Do not permanently kill a session on a session-limit hit — re-arm it when the limit window resets, or surface an explicit, actionable dead state.
- Do not tear down active sessions on a recoverable disconnect; the existing backoff already handles short outages.
- Propagate session death to the client, so the mobile app stops presenting dead sessions as live and stops silently swallowing messages sent into them.
3 Comments
I’d separate the durable task from the remote-control session. The session is a disposable worker/lease: it can hit a quota, lose its network, or be replaced without making the task disappear.
For each task, keep a small state record outside the transcript: task id and monotonic revision, last accepted artifact, pending approval, lease owner and expiry, retry state, and an explicit terminal/dead reason. A reconnect should resume from that bounded state and replay missed revisions; it should not depend on the old conversation still being alive.
When a session becomes unavailable, the client should stop presenting it as alive and route new messages to the task inbox (or reject them visibly), rather than accepting input into a dead transcript. Background notifications should be idempotent projections of task state, so retries or quota resets cannot create duplicate or misleading messages. That turns a transient disconnect into “reconnect and resume task X,” while a real terminal failure remains visible and actionable.
I build cmdop, so I’m biased — we’re working on the same machines-and-agent-sessions problem with outbound-only connectivity and a browser messenger. The useful boundary for us is that the machine remains the execution authority while the remote client is only the conversation surface.
Confirming this on macOS with Claude Code 2.1.220 (i.e. still present eight releases after the 2.1.212 report).
Adding a data point from the desktop app that overlaps with this issue: on top of sessions dying on transient drops, the desktop app also deliberately disconnects idle sessions — and the mobile app renders both cases identically as "Disconnected", so users can't tell a recoverable pause from a permanently dead session.
Environment
1.26832.0(bundled claude-code2.1.222), macOS26.5.2What the logs show (
~/Library/Logs/Claude/main.log)Every session gets a 15-minute idle timer, re-armed on each interaction:
When it expires, the app disconnects the session on purpose — this repeats every 15 min all day for any idle session:
The 900s value is hardcoded in the app bundle with no user-facing setting:
Related lifecycle behaviors in the same logs: all sessions stop on app quit (
[CCD] Stopping 3 active session(s) on quit), and a governor can evict idle sessions under memory pressure ([CliGovernor] memory pressure (warning): would evict N idle session(s)).Why this matters for this issue
Requests
idleTimeoutMsconfigurable.