[BUG] Long-running `claude remote-control` server silently breaks after a CLI self-update — new sessions fail with EPERM while the server still reports connected

Open 💬 1 comment Opened Jun 22, 2026 by RazorII

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

I run claude remote-control as a persistent server (a launchd LaunchAgent with RunAtLoad + KeepAlive) so I can start sessions on my Mac from the phone. claude-code auto-updated itself while that server was running, and from that point every new session spawned from the phone / claude.ai/code failed with An internal error occurred (EPERM).

The misleading part: the server kept reporting connected the whole time — green dot on the phone, a live ESTABLISHED :443 relay socket, launchctl print showing running, and the log printing Connected · Capacity 0/32. So it looks completely healthy but cannot spawn a single session, and nothing recovers on its own (KeepAlive never fires because the process never crashes or exits).

A plain restart of the server fixed it immediately, with no permission / Full Disk Access change of any kind — the key signal that this is the running process going stale across its own update, not a TCC / entitlement misconfiguration.

What Should Happen?

After the on-disk CLI changes, a long-running remote-control server should either:

  1. gracefully re-exec onto the new binary and keep spawning sessions; or
  2. at minimum, fail loudly and actionably (a clear message telling me to restart) instead of an opaque EPERM, and stop advertising itself as connected / healthy when it can no longer spawn sessions.

It should not keep showing a green / connected status on the phone while every new session dies.

Error Messages/Logs

The CLI self-updated at ~09:40 (the on-disk `package.json` mtime). The server process had started at 09:31 — before the update — and kept running. Both session attempts afterward failed:


[14:21:03] Session failed: error: An internal error occurred (EPERM) cse_...
[20:21:53] Session failed: error: An internal error occurred (EPERM) cse_...


Throughout, the server held a live ESTABLISHED :443 socket and logged `Connected` / `Capacity 0/32`. KeepAlive never intervened because the process never crashed or exited. The opaque EPERM line is the only error surfaced — no path or stack trace.

Steps to Reproduce

  1. Start claude remote-control as a long-lived server and leave it running (a launchd KeepAlive agent makes this easy, but a plain long-running terminal session reproduces it too).
  2. While it is running, let the CLI update underneath it — auto-update, claude update, or npm i -g @anthropic-ai/claude-code@latest — so the on-disk @anthropic-ai/claude-code install changes while the process keeps running.
  3. From the Claude mobile app (or claude.ai/code), open the environment — it still shows connected / green — and start a new session.
  4. Result: Session failed: error: An internal error occurred (EPERM). Repeats for every new session; the environment keeps advertising itself as connected.
  5. Restart the server (launchctl kickstart -k ..., or /remote-control then Disconnect then reconnect). Sessions work again immediately. No permission change was needed.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.185 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Environment: macOS (Darwin 25.5.0), Apple Silicon; claude-code 2.1.185 installed as an npm global under nvm (node v22.22.3); logged in via claude.ai subscription; spawn mode same-dir; server run as a persistent launchd LaunchAgent (RunAtLoad + KeepAlive).

Hypothesised cause (not confirmed): the self-updater rewrites the on-disk install while the server keeps executing pre-update code in memory; session spawning then crosses the old-process / new-on-disk-install boundary and fails with EPERM. Because a plain restart (no FDA / permission change) fully resolves it, this points to a stale process running across its own update rather than a permissions problem.

Impact: affects anyone running remote-control as a persistent server — the intended setup for always-available phone access — and auto-update is on by default, so the collision is reachable with no unusual configuration. The failure is silent: the device shows green and connected, but every session fails, which reads like an account or network problem rather than a stale server.

Workaround: restart the server after any CLI update. I run a 10-minute watchdog that compares the on-disk install's package.json mtime against the server process start time and kickstart -ks onto the new binary when the install is newer (deferring while a session is active so it never kills live work).

Related:

  • Sibling reliability bug (network reconnect, not update): #34255 (silent stale-but-alive on connection drop); umbrella #33041 — same family of 'server looks healthy but cannot serve, no self-recovery'.
  • Same class — CLI self-update silently breaking a long-lived integration: #69546 (Chrome native host dies on every version bump).
  • Adjacent EPERM / after-update reports: #48238 (/remote-control init fails after updating), #48244 (spawn EPERM).

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗