Remote Control: CCR v2 worker registration fails with 404 when re-launching a previously-registered environment

Status Open
Reported on v2.1.228
Maintainer reply None cached
Activity 4 comments · opened Aug 12, 2026

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 update on 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 status confirms loggedIn: true, same org, on every machine

Steps to reproduce

  1. claude remote-control --name "X" in a directory that has never been used for Remote Control before → registers cleanly, no error.
  2. Stop the process (Ctrl+C, close the terminal, or disconnect the SSH session it was running in).
  3. 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
`
The bridge still shows
Connected, 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 update reported 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.

View original on GitHub ↗

3 Comments

Roorn · 1 month ago

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-control under 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-agents symptom).

**The dead id belongs to a session that ended cleanly.** With journalctl --all the 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 --all the 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 plain journalctl, invisible to grep. journalctl --all shows 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 a session_ prefix where the error prints cse_ (same suffix; that prefix mismatch is why grepping for the printed id finds nothing, as tonydehnke found in #77372):

{
  "sessionId": "session_01Acwizs…",      ← error prints cse_01Acwizs…
  "environmentId": "env_01Gf2…",
  "source": "standalone",
  "pid": <pid of the currently running worker>
}

And it keeps being written back with the live worker's pid, so it never ages out. Three observations from the last two days:

  • The restart of Aug 17 began at 23:07:12; the new worker was up at 23:07:13 and its pid was in the pointer at 23:07:15 — about two seconds into its life — with the same dead session id (mtime recorded live; since overwritten by the next rewrite).
  • The registration that failed at 23:07:19 failed on exactly that id, four seconds after it was written back.
  • Mid-run rewrites at 39 hours and again at 9 hours into a worker's life.

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.

JOduMonT · 1 month ago

as little it can be
I fought with rc remote-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 extension

remark I'm running claude code on Ubuntu 26.04LTS inside WSL2

ideesnoires · 1 month ago

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. Next claude rc invocation — in any directory, not just the one that was interrupted — fails immediately with:

Error: CCR v2 worker registration failed for session cse_XXXXXXXXXXXXXXXXXXXXXXXX: Request failed with status code 404
Environment preserved. Restart `claude remote-control` to reconnect existing sessions.

Found the client-side state: each project directory keeps ~/.claude/projects/<project>/bridge-pointer.json, e.g.:

{"sessionId":"session_...","environmentId":"env_...","source":"standalone","pid":60757,"procStart":"..."}

If the process at that pid is 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-dead cse_... session, and registration fails.

Workaround: delete the stale bridge-pointer.json (verify pid is dead first) before relaunching. Confirmed this clears the error without needing a new environment.

This might be the same root cause as #90777 (activeSessionIds never 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 client kill -0 the recorded pid before trusting a bridge pointer, and/or having the server accept re-registration for a cse_ id that's already gone instead of 404ing.

Showing cached comments. Read the full discussion on GitHub ↗