remote control: bridge restart rotates environment id and silently auto-disables all scheduled routines (auto_disabled_env_not_found); plus a 6h registration crash loop
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 rc --name claude-home as an always-on bridge on a Mac (launchd KeepAlive). Two related problems, one incident with full forensics below.
Problem 1: environment identity is tied to the bridge process lifetime.
On shutdown the bridge deletes its environment (DELETE /v1/environments/bridge/<env_id>), and on start it registers a brand new env id (POST /v1/environments/bridge). Consequences:
- Every scheduled routine (RemoteTrigger) is pinned to a specific
environment_id. After any bridge restart, the routine's next fire ends withended_reason=auto_disabled_env_not_foundand the trigger is silently disabled. Nothing re-enables it when the bridge comes back. For unattended nightly automation this means silent multi-day outages (it has bitten my nightly pipeline 3 times in 10 days: Jun 22, Jun 28, Jul 1). - The claude.ai web/mobile "Local" chat list is a live view of attached sessions, so every restart blanks it and previous RC chats become unreachable from the UI (transcripts survive on disk). Related: #53563.
Problem 2: registration crash loop with no backoff and no durable error.
Incident timeline (2026-06-30, times PT, logs in the Logs field):
- 16:14:32: after 8.8 days up, the bridge does a routine graceful self-shutdown at its token-refresh boundary:
[bridge:shutdown] Shutting down 17 active session(s), workers SIGTERM, env deleted, exit 0. launchd relaunches. - 16:14:37 to 22:15: every relaunch exits code 1 roughly 330-370ms after
POST /v1/environments/bridge: ~700 attempts over ~6 hours, ~30s apart (launchd throttle is the only backoff). Ruled out: machine asleep (kept awake, verified), network down (independent monitor showed Google APIs reachable mid-loop at 17:03), CLI auto-update. - 22:15:35: one attempt finally succeeds and registers a NEW env id. All triggers still pointed at the deleted env; my nightly routine had fired at 22:00 into the dead env, got
auto_disabled_env_not_found, and was disabled.
The registration failure reason is not recoverable after the fact: the error prints only to the child's stdout/stderr. I have since instrumented my wrapper to capture a bounded stderr tail on nonzero exit, so the next occurrence will include the actual startup error.
Workaround I run today (reference implementation, happy to share): an external healer that polls GET /v1/environments (keychain OAuth token), detects rotation, and re-points all managed triggers via the RemoteTrigger tool in a headless claude -p run (the trigger update shallow-replaces job_config.ccr, so it must resend the full ccr). It works but authenticates with the same keychain token the bridge maintains, which can be stale exactly when a heal is needed. Native support would eliminate this class of glue.
What Should Happen?
- Environment identity durable across bridge restarts: re-register under the same env id, or a stable host+name alias that scheduled routines can bind to.
- Failing that: when a bridge re-registers, re-point and re-enable triggers that were auto-disabled with env_not_found for that host's previous env, instead of leaving them silently disabled.
- Registration failures: exponential backoff instead of a 6h tight loop, and log the rejection reason somewhere durable (debug log), not only child stdout.
Error Messages/Logs
# launchd records, 2026-06-30 PT
16:14:36.668 com.fede.claude-remote-control [29799] exited due to exit(0), ran for 757270984ms (~8.8 days)
16:14:37.011 com.fede.claude-remote-control [7666] exited due to exit(1), ran for 342ms
16:15:07.382 com.fede.claude-remote-control [7883] exited due to exit(1), ran for 360ms
... ~700 further relaunches, all exit(1) within ~330-370ms, ~30s apart, until 22:15:35 PT
# bridge debug log
2026-06-30T23:14:32.666Z [DEBUG] [bridge:shutdown] Shutting down 17 active session(s)
# after recovery, a new env id appears in every bridge API call:
2026-07-01T13:10:44.695Z [DEBUG] [bridge:api] POST /v1/environments/env_01MK9.../bridge/reconnect
# claude.ai notification email, received 3x in 10 days (Jun 22, Jun 28, Jul 1):
"Routine disabled — environment no longer available. The environment for routine <name>
is no longer available, so we have disabled the routine."
Steps to Reproduce
- Run
claude rc --name <name>as an always-on bridge (launchd KeepAlive) on macOS. - Create a scheduled routine (RemoteTrigger) whose
job_config.ccr.environment_idpoints at the bridge's environment. - Restart the bridge (or simply wait: it self-restarts at its token-refresh boundary, ~32h typical, up to ~9 days observed).
- Observe: the old environment is deleted on shutdown and a new env id is registered on start; the routine's next fire ends with
ended_reason=auto_disabled_env_not_foundand the trigger is disabled; the web "Local" chat list blanks.
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.160 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
- macOS 26.5.1 (arm64), bridge under launchd KeepAlive via a pty wrapper.
- Reproduced on 2.1.160 (auto-update lags here; latest is 2.1.198 at filing time). The behavior is architectural (env deleted on shutdown, new env registered on start) and has been constant since at least early June across versions.
- Related: #53563 (token expiry kills active RC sessions and orphans the environment; this report is about the scheduled-routine and crash-loop consequences). Possibly also relevant to #65926 (bridge env handling).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗