[BUG] `claude remote-control` (server mode) fails registration with 400 on legacy `/v1/environments/bridge`, while `--remote-control` succeeds via v2 session path

Status Fixed / completed
Reported on v2.1.222
Maintainer reply None cached
Activity 1 comment · opened Aug 5, 2026 · closed Aug 23, 2026

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?

What's Wrong?

claude remote-control (server mode) fails immediately at the registration phase with Error: Registration: Failed with status 400. No session URL or QR code is ever produced.

On the same machine, same account, same directory, and same binary, both claude --remote-control (interactive) and /remote-control (from an existing session) connect successfully.

Debug logs show the two modes use different protocol paths:

  • Server mode registers a v1 environment: [bridge:api] POST /v1/environments/bridge → 400
  • Interactive mode never calls that endpoint. It creates a session and builds a v2 transport: [remote-bridge] Created session cse_... → v2 session URL: /v1/code/sessions/cse_...

This suggests server mode still uses the legacy environment-registration endpoint while interactive mode has been migrated to the v2 session flow, and the legacy endpoint now rejects the client's registration body.

Secondary defect: the CLI does not log the 400 response body, only the outbound POST. The server's rejection reason is invisible even with --debug-file, which makes the failure undiagnosable without proxy-level capture.

What Should Happen?

claude remote-control should register successfully and serve on-demand sessions, as documented at https://code.claude.com/docs/en/remote-control — printing a session URL and QR code, then waiting for remote connections.

Failing that, the error should surface the server's rejection reason rather than a bare status code.

Error Messages/Logs

# Terminal output (identical across all flag combinations tried)

$ claude remote-control
Error: Registration: Failed with status 400

# Server mode debug log (fails)

[DEBUG] [bridge:init] bridgeId=c2805383-... dir=/home/<user>/<project> branch=feature/rfc-0010 gitRepoUrl=git@github.com:<org>/<repo> machine=home-pc
[DEBUG] [bridge:init] apiBaseUrl=https://api.anthropic.com sessionIngressUrl=https://api.anthropic.com
[DEBUG] [bridge:init] sandbox=false debugFile=/tmp/rc-server.log
[DEBUG] [bridge:api] POST /v1/environments/bridge bridgeId=c2805383-...
[DEBUG] Released PID lock for 2.1.222

# No response line is logged. The process exits immediately after the POST.

# Interactive mode debug log (works), same directory

[DEBUG] [remote-bridge] Created session cse_01J4Lz...
[DEBUG] [remote-bridge] Fetched bridge credentials (expires_in=28800s)
[DEBUG] [remote-bridge] v2 session URL: https://api.anthropic.com/v1/code/sessions/cse_01J4Lz...
[DEBUG] [bridge:repl] CCR v2: worker sessionId=[REDACTED] epoch=1 (from /bridge)
[DEBUG] [remote-bridge] v2 transport created (epoch=1)
[DEBUG] [bridge:repl] handleStateChange state=ready detail="undefined" cancelled=true outboundOnly=false

Steps to Reproduce

  1. Authenticate with a claude.ai account: claude auth login (API key auth is not supported for Remote Control)
  2. Create an empty non-git directory to rule out repository metadata: mkdir /tmp/rc-test && cd /tmp/rc-test
  3. Run claude remote-control
  4. Observed: Error: Registration: Failed with status 400, process exits immediately
  5. In the same directory, run claude --remote-control
  6. Observed: succeeds, prints a session URL and QR code, session appears in the Code tab of the Claude app

No project files, configuration, or repository state are required — step 2 uses an empty directory and reproduces identically to a real project.

To capture the logs above, add --debug-file /tmp/rc-server.log to step 3 and --debug-file /tmp/rc-int.log to step 5, then:

diff <(grep bridge /tmp/rc-server.log) <(grep bridge /tmp/rc-int.log)

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.222 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

Environment

  • Platform: linux-x64
  • Install method: native (~/.local/share/claude/versions/2.1.222)
  • Auth: claude.ai OAuth — interactive Remote Control works, so credentials and scopes are valid
  • Plan: Max
  • ANTHROPIC_BASE_URL unset; no Bedrock/Vertex/Foundry variables set
  • No feature-flag-disabling variables set (DISABLE_TELEMETRY, DO_NOT_TRACK, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_GROWTHBOOK)

claude doctor output

Claude Code doctor
Running: native (2.1.222)
Commit: fbf49312c284
Platform: linux-x64
Path: /home/<user>/.local/share/claude/versions/2.1.222
Config install method: native
Search: OK (bundled)
Auto-updates: enabled
Auto-update channel: latest
Last update attempt: success → 2.1.222 (2026-08-05)
Remote Control
Control this session from claude.ai/code or the Claude mobile app
No installation issues found.

Ruled out

  • Git metadata — reproduces identically in a fresh non-git directory, where no git_repo_url is sent
  • Registration payload fields — identical 400 across --capacity 1, --capacity 2, --spawn session, and --name "test" --capacity 1, so neither max_sessions nor the auto-generated hostname-based name is the rejected field
  • Auth / scopes / plan eligibility — interactive Remote Control works on the same credentials; the failure is 400, not 401/403
  • Stale environments — no orphaned Remote Control sessions listed at claude.ai/code
  • Version staleness — on latest (2.1.222); claude update reports up to date
  • Environment variables — none of the documented Remote Control blockers are set

Suggested fixes

  1. Migrate server mode to the same v2 session path interactive mode uses, or fix the legacy endpoint's handling of the server-mode registration body
  2. Log the response body on registration failure so the rejection reason is visible with --debug-file

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗