Remote Control: CCR v2 worker registration fails with 404 when re-launching a previously-registered environment
Summary
claude remote-control fails to register its CCR v2 worker (Error: CCR v2 worker registration failed for session cse_XXXXXXXX: Request failed with status code 404) when re-launching on an environment that was already registered before (the same env_... ID is reused server-side for a given account+directory+machine combination). A brand-new environment (never launched before under that account) registers cleanly every time.
The bridge still reports Connected, so the failure is easy to miss, but the practical impact is that cross-machine session discovery via /list-agents (ListAgents) never shows sessions from an affected environment — even with Remote Control simultaneously connected on multiple machines under the same account.
Environment
- Claude Code CLI: 2.1.228 (confirmed up to date via
claude updateon every machine involved) - Single Claude Max subscription, same org (
orgId) on all machines - Machines: macOS (MacBook Pro), macOS (Mac Mini), Synology DSM (NAS, accessed via SSH)
claude auth statusconfirmsloggedIn: true, same org, on every machine
Steps to reproduce
claude remote-control --name "X"in a directory that has never been used for Remote Control before → registers cleanly, no error.- Stop the process (Ctrl+C, close the terminal, or disconnect the SSH session it was running in).
claude remote-control --name "X"again in the same directory → fails on startup with:
```
Error: CCR v2 worker registration failed for session cse_XXXXXXXX: Request failed with status code 404
Connected
The bridge still shows , but the environment never becomes discoverable from another machine's /list-agents`.
Evidence (same account, same day, 3 independent machines)
| Machine | Directory | Environment ID | Registration | CCR v2 error |
|---|---|---|---|---|
| MacBook Pro | ~/Desktop | env_0174inQqWGZ7Q2K6hqQemsah | 1st launch ever | No |
| MacBook Pro | ~/Desktop (same env, relaunched) | env_0174inQqWGZ7Q2K6hqQemsah | Relaunch | Yes |
| Mac Mini | ~/DS-Builder | env_01GfsCL3uhDdu2VJ2CnGkHGY | Relaunch (×2, different times) | Yes (both times) |
| Mac Mini | ~/test-rc (freshly created dir) | new env | 1st launch ever | No |
| NAS (Synology DSM) | ~ | env_017LMwYYknmnm6JB1Qi82cNs | 1st launch ever | No |
Every first-time registration of a new environment succeeded; every relaunch of a previously-registered environment failed with the same 404, across two different physical Macs.
What we ruled out
- CLI version: all three machines were already on the latest version (
claude updatereported up to date). - Auth/account/subscription: identical
orgId,loggedIn: true, Claude Max on all three machines. - Local install corruption: on the Mac Mini specifically, registering a brand-new environment (
~/test-rc) worked perfectly right after the existing environment (~/DS-Builder) had just failed in the same install — ruling out a broken local install as the cause.
This points to a server-side issue with re-registering (resuming) a CCR v2 worker for a previously-created environment, rather than a client-side or account-level problem.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Third machine reproducing the relaunch 404 (fourth in your combined dataset — your NAS row only shows a clean first launch), on a longer window, plus a local mechanism that may explain why re-launches fail while fresh directories register cleanly.
Setup: headless Ubuntu Server 26.04,
claude remote-controlunder a systemd system unit, always on; native install, currently 2.1.234.Matching your pattern: 26 consecutive service starts (Jul 31 – Aug 17, the most recent start) each log the CCR v2 worker-registration 404 exactly once, 6–12 seconds after start, always for the same session id. As in your report the bridge still connects afterwards, so it's easy to miss — and in daily use here, phone sessions on this machine have kept working regardless (my observation, not yours; I haven't tested your cross-machine
/list-agentssymptom).**The dead id belongs to a session that ended cleanly.** With
journalctl --allthe id appears exactly once before the failures:Session completed (1m 41s)on Jul 29 — a short session, created within minutes of the environment id itself first appearing, that completed normally. No crash. That matches your stop conditions (Ctrl+C, closed terminal, dropped SSH) better than any crash story: a normally ended session left an id behind that re-registration has tripped over at every start since. (This also corrects the origin I gave in my Aug 11 comment on #77372, which blamed a kernel OOM of Aug 2 — with--allthe series demonstrably starts Jul 31, and the journal shows the id completing healthily on Jul 29.)Where the series starts is sharp, with one confound: on Jul 31, after a reboot and a ~6-minute credential-loss crash loop (11 starts, unrelated), a start at 08:54 on the then-installed CLI — a long-stale native install stuck on 2.1.197, auto-updates off — connected with no registration error. Minutes later that install was updated in place to 2.1.220 (a stray npm-global duplicate installed that morning as a repair attempt was removed at the same time) and the service restarted: the first start on 2.1.220 logged the first 404 six seconds in, and all 26 starts since (through 2.1.234, 6 reboots) repeat it. Caveat: successful registration is silent, so I can't tell whether 2.1.197 was re-registering successfully or simply didn't exercise this path.
(Measurement tip that cost me two weeks of miscounting: my unit's early logs stored raw ANSI codes, and those lines — including the first two 404s and the healthy
Session completed— render as[blob data]in plainjournalctl, invisible to grep.journalctl --allshows them.)The mechanism datapoint. The CLI keeps a pointer file,
~/.claude/projects/<project>/bridge-pointer.json, which here still contains the dead session's id — with asession_prefix where the error printscse_(same suffix; that prefix mismatch is why grepping for the printed id finds nothing, as tonydehnke found in #77372):And it keeps being written back with the live worker's pid, so it never ages out. Three observations from the last two days:
If the worker re-submits the persisted id on startup, your table follows directly: a fresh directory has no pointer → new session id → clean; a previously-registered one carries a session id the server no longer accepts → 404. That would make the server-side part simply "that session no longer exists", and the bug the client persisting and reusing a dead session id with nothing that lists it and nothing that can delete it (that side is tracked in #77372). Stated plainly: the re-submit step is inference from timing and the matching suffix, not a packet capture — your server-side reading could still be right, in which case the pointer is a symptom rather than the cause.
One footnote on "the same
env_...ID is reused server-side": mostly true here too — the same env id has survived 38 service restarts and 7 reboots since Jul 29 — but my journal does show one changeover: a different id on Jul 28 that demonstrably survived the three reboots of an in-place OS upgrade that evening, and was replaced only at the next morning's boot. So the binding is sturdy but not immutable.Happy to delete the pointer file and report whether the next start registers cleanly — haven't yet, since this worker is in production use.
as little it can be
I fought with
rcremote-control--remote-control... (@claude your doc is a mess) for almost 12 hours.I was able to get ride of this Error: CCR v2
by turning off
Auto-install IDE extensionremark I'm running claude code on Ubuntu 26.04LTS inside WSL2
Same error, different trigger and a client-side artifact that may be relevant.
Environment: macOS,
claude rc(standalone Remote Control bridge), single repo directory.Repro:
claude rc, then end the process with a plain Ctrl+C (SIGINT) — the normal, everyday way to stop it, not a crash or force-kill. Nextclaude rcinvocation — in any directory, not just the one that was interrupted — fails immediately with:Found the client-side state: each project directory keeps
~/.claude/projects/<project>/bridge-pointer.json, e.g.:If the process at that
pidis no longer running — which is already true after an ordinary Ctrl+C, since the pointer is apparently never cleared on SIGINT — the next launch still tries to reconnect using it, the server 404s on the now-deadcse_...session, and registration fails.Workaround: delete the stale
bridge-pointer.json(verifypidis dead first) before relaunching. Confirmed this clears the error without needing a new environment.This might be the same root cause as #90777 (
activeSessionIdsnever written on ungraceful shutdown) — in both cases the client has no way to distinguish "worker died, pointer is stale" from "worker still owns this session," so it keeps re-presenting dead state to the server (or vice versa) and gets a 404. Might be worth having the clientkill -0the recordedpidbefore trusting a bridge pointer, and/or having the server accept re-registration for acse_id that's already gone instead of 404ing.