[BUG] Remote Control fails at bridge init: /v1/code/sessions intermittently 401s a valid OAuth token (~50-70% of requests, split backend fleet)

Status Open
Maintainer reply None cached
Activity 6 comments · opened Jul 17, 2026

Summary

Interactive --remote-control shows the × Remote Control Failed banner at session start. Root cause (reproduced outside the CLI): api.anthropic.com/v1/code/sessions intermittently returns 401 "Authentication failed" for a valid OAuth token — identical back-to-back requests alternate between 200 and 401, which looks like a split backend fleet (rolling deploy or bad subset of instances). The CLI only retries 3 times, so with ~50% per-request failure the bridge init frequently loses all three and gives up.

Re-running /login does not help (and can't — see evidence below).

Environment

  • Claude Code v2.1.212, Windows 10 (10.0.19045)
  • Claude Max (personal), OAuth login, scopes include user:sessions:claude_code
  • First observed 2026-07-17 ~10:36 UTC; a session launched at 10:34 UTC connected fine, sessions launched from 10:36 onward fail

Debug log (from claude --remote-control <name> --debug)

Before re-login (session create passes on retry, /bridge credentials fetch fails 3/3):

10:44:29 [code-session] Session create failed 401: Authentication failed
10:44:29 [remote-bridge] createCodeSession failed (attempt 1/3), retrying in 412ms
10:44:30 [remote-bridge] Created session cse_01Gw7625bCM136xwhmzuicXA
10:44:31 [code-session] /bridge failed 401: Authentication failed
10:44:31 [remote-bridge] fetchRemoteCredentials failed (attempt 1/3), retrying in 594ms
10:44:31 [code-session] /bridge failed 401: Authentication failed
10:44:32 [code-session] /bridge failed 401: Authentication failed
10:44:32 [remote-bridge] Creds failed; onStateChange set, msg="Remote credentials fetch failed — see debug log"
10:44:32 [bridge:repl] handleStateChange state=failed detail="Remote credentials fetch failed — see debug log"

After a fresh /login (10:53 UTC) — same failure, now at session create:

10:54:46 [code-session] Session create failed 401: Authentication failed
10:54:46 [remote-bridge] createCodeSession failed (attempt 1/3), retrying in 385ms
10:54:46 [code-session] Session create failed 401: Authentication failed
10:54:48 [code-session] Session create failed 401: Authentication failed
10:54:48 [bridge:repl] handleStateChange state=failed detail="Session creation failed — see debug log"

Evidence the token is valid and the failure is server-side

All of the following used the freshly-minted accessToken from ~/.claude/.credentials.json (expiry valid, subscriptionType: max):

  1. GET api.anthropic.com/api/oauth/profile200 every time.
  2. Normal CLI inference on the same token works throughout (the session doing this debugging runs on it).
  3. GET api.anthropic.com/v1/code/sessions?limit=1 with anthropic-version: 2023-06-01, 8 identical requests over ~10 seconds:

``
200 401 200 200 401 200 401 401
``

  1. Even the 401s are inconsistent with each other: without the anthropic-version header, responses alternate between 401 authentication_error and 400 "anthropic-version: header is required" — i.e. some backends pass auth and fail on header validation, others reject the same token at the auth layer. Paired examples seconds apart, same token:
  • req_011Cd7WjLcxvngbdyqBxigQa → 401 Authentication failed
  • req_011Cd7WjPrg3XJtPg9TvLxpZ → 400 missing anthropic-version (auth passed)
  1. The 401 responses still include the resolved anthropic-organization-id response header, so the token is being recognized before rejection.
  2. Worker-mode claude remote-control (which registers via /v1/environments/bridge instead) connected instantly on the same credentials — only the /v1/code/sessions service is affected.

Expected

Consistent auth decisions for the same valid token; and/or a bridge init that survives a transiently-flaky backend (3 rapid retries is too few when the failure mode is per-request roulette — a longer/backoff retry like the post-connect reconnect path already has would have masked this entirely).

Actual

~50% of requests to /v1/code/sessions 401; bridge init exhausts its 3 attempts and Remote Control permanently shows the Failed banner for that session.

🤖 Generated with Claude Code

View original on GitHub ↗

6 Comments

mklod · 1 month ago

Two follow-ups after another hour of debugging:

1. Failure is sustained and per-request (not connection-sticky). ~50 min after first report, the 401 rate is holding or worse (8/12, then 6/10 identical requests). It is not tied to connection reuse or HTTP version — on a single keep-alive connection I got 200 then five 401s; fresh HTTP/1.1 connections and Node's fetch (the CLI's stack) show the same roulette. So retrying inside one process doesn't dodge a "bad backend" — every request is an independent coin flip.

2. The real UX problem: a failed initial connect permanently disables Remote Control for that session. From the bundled code, when bridge init returns null the client runs replBridgeEnabled: false and never retries — unlike the post-connect drop path, which patiently reconnects with backoff for up to 10 minutes. With today's ~50-65% per-request failure rate compounding across the several sequential authenticated calls init makes, most fresh sessions land in the permanently-failed state. For users running many parallel sessions that means manually toggling /remote-control in every window, repeatedly, until each one wins the coin flip.

Request: give the initial connect the same background retry/backoff loop the reconnect path already has. That one change would have made this server incident a non-event (sessions would self-heal when the fleet recovers) instead of a hard outage requiring per-session manual intervention.

🤖 Generated with Claude Code

chadneal · 1 month ago

Corroborating from macOS (also v2.1.212, Max, claude.ai OAuth): I filed #78470 with the same signature minutes after this issue, before finding it. Extra data points consistent with the split-fleet read: (1) within a single process and a single in-memory token, /bridge went 401, 401, success across 1.6s (10:54:07-08 UTC) and then connected normally; (2) in a run where /bridge failed 3/3, the same token archived the just-created cse_ session with status 200 one second later; (3) onset on my side was ~10:07 UTC, and status.claude.com showed Degraded Performance for api.anthropic.com, claude.ai, and Claude Code from 06:47 UTC. Also seconded that worker-mode claude remote-control connected fine throughout, so only the /v1/code/sessions path is affected.

mklod · 1 month ago

Status update: the endpoint has degraded from intermittent to fully down. Automated monitoring (5 probes every ~2 min, same valid token) has returned 0/5 successes for 10 consecutive rounds (~20+ minutes of 100% 401s on /v1/code/sessions, while /api/oauth/profile continues to return 200). Remote Control is now hard-down for this account rather than a retry-luck problem.

mklod · 1 month ago

Recovery: as of ~14:09 UTC the endpoint is healthy again (5/5 monitored probes returning 200) and a real --remote-control bridge init now completes (one 401 still occurred on the first createCodeSession attempt but the retry succeeded; credentials fetch and transport connect were clean). Total observed impact for this account: ~3.5 hours of Remote Control being unusable. The design-gap request stands: a background retry on failed init would have made this self-healing.

sidoyu · 1 month ago

Recurrence data point: the code-session endpoints degraded again for this account roughly an hour after the ~14:09 UTC recovery reported above.

Environment: Claude Code v2.1.212, macOS (Darwin 25.5.0) arm64, Max subscription, claude.ai OAuth. Access token freshly refreshed at 14:50 UTC (verified via keychain expiry metadata), so token staleness is excluded.

Timeline (2026-07-17 UTC) — same machine, same account, same token:

| time | action | result |
|---|---|---|
| 15:05:27 | manual /remote-control in an existing interactive session | ✅ connected |
| 15:06:10 | new interactive session launched with --remote-control (flag verified attached via ps) | ❌ "Remote Control failed" banner at startup |
| 15:07:39 | fresh diagnostic launch, --remote-control --debug-file | ❌ log below |
| 15:08:52 | manual /remote-control in the 15:06 session | ✅ connected |

Launch-time init went 0/2 while manual /remote-control went 2/2 inside the same 3.5-minute window. That matches the per-request 401 roulette + 3-attempt budget described in this issue, amplified by the permanent give-up after a failed init (manual /remote-control being the only retry path in the process).

Debug log from the 15:07:39 failure — eligibility check passed, session create passed, /bridge lost all three attempts:

15:07:39.893 [DEBUG] Passes: Using fresh cached eligibility data
15:07:40.597 [DEBUG] [remote-bridge] Created session cse_012SCmaFSmGxca62wovfykpr
15:07:40.853 [DEBUG] [code-session] /bridge failed 401: Authentication failed
15:07:40.853 [DEBUG] [remote-bridge] fetchRemoteCredentials failed (attempt 1/3), retrying in 585ms
15:07:41.683 [DEBUG] [code-session] /bridge failed 401: Authentication failed
15:07:41.684 [DEBUG] [remote-bridge] fetchRemoteCredentials failed (attempt 2/3), retrying in 785ms
15:07:42.722 [DEBUG] [code-session] /bridge failed 401: Authentication failed
15:07:42.722 [DEBUG] [remote-bridge] Creds failed; onStateChange set, msg="Remote credentials fetch failed — see debug log"
15:07:42.724 [DEBUG] [bridge:repl] Init returned null (precondition or session creation failed); consecutive failures: 1
15:07:43.082 [DEBUG] [code-session] Archive session_012SCmaFSmGxca62wovfykpr status=200

Two details consistent with earlier observations here: the same process archived the just-created session with status=200 one second after /bridge 401'd 3/3, and normal inference + MCP traffic on the same token worked throughout — only the code-session path is affected.

status.claude.com was still showing Degraded Performance for api.anthropic.com / Claude Code at the time (incident last updated 14:57 UTC), so this may simply be the same incident continuing past the partial recovery — but it does mean the outage window is longer/waves rather than a single resolved blip.

Seconding the design-gap feedback above: a background retry (or any retry path after init failure that doesn't require a human typing /remote-control) would have made every one of these launch failures self-healing.

raylu2099 · 1 month ago

**Additional data point: the "gives up forever" retry policy turns an intermittent 401 into a multi-day silent outage for unattended sessions**

Environment: Claude Code on Linux (Synology DSM 7, x86_64), claude --remote-control <name> running 24/7 as an unattended daemon under cron + tmux, Claude Max OAuth.

Same root cause as reported here (intermittent 401 on the bridge-init endpoints). What I'd like to add is the operational consequence of the retry policy when nobody is watching the terminal:

  • Once the 3 attempts (~1.3s) are exhausted, the CLI never retries again for the entire lifetime of the process — but the process itself stays perfectly healthy-looking: Claude Max banner, non-zero ESTABLISHED connections (MCP/telemetry keep the pool warm), no restart loop, no non-zero exit.
  • Every local health signal therefore reads green. In our case Remote Control was invisible in the phone/desktop host list for 3 days (2026-07-14 → 07-17) while three independent watchdogs all reported healthy the whole time.
  • The only observable signal is the Remote Control failed text rendered in the TUI pane. We now scrape the tmux pane for it and recycle the session on first sight (kill + relaunch with --continue). That works because the 401 is intermittent — a fresh process is just a new dice roll — but it's a workaround for a client-side retry gap, not a fix.

Suggestions, in order of preference:

  1. Background retry with exponential backoff after bridge init fails, for the life of the process. An intermittent server-side 401 shouldn't be terminal for a long-lived session.
  2. Failing that, a machine-readable failure state (non-zero exit, status file, or a stable status-line token) so supervisors don't have to scrape TUI text to notice.

Happy to provide --debug logs from the Linux side if that's useful.