Skip to content

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 #73565

Description

@fedeum

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • 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:

  1. Every scheduled routine (RemoteTrigger) is pinned to a specific environment_id. After any bridge restart, the routine's next fire ends with ended_reason=auto_disabled_env_not_found and 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).
  2. 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: remote-control: 403 token expiry kills all active sessions instead of refreshing #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?

  1. 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.
  2. 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.
  3. 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

  1. Run claude rc --name <name> as an always-on bridge (launchd KeepAlive) on macOS.
  2. Create a scheduled routine (RemoteTrigger) whose job_config.ccr.environment_id points at the bridge's environment.
  3. Restart the bridge (or simply wait: it self-restarts at its token-refresh boundary, ~32h typical, up to ~9 days observed).
  4. 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_found and 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:routinesClaude Code routines on web, used for scheduled tasks, webhook-triggered tasks, etc.bugSomething isn't workinghas reproHas detailed reproduction stepsplatform:macosIssue specifically occurs on macOS

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions