OAuth token exchange fails with HTTP 400 on fresh /login and setup-token (VS Code Remote Tunnel to Linux)

Status Open
Reported on v2.1.271
Maintainer reply None cached
Activity 1 comment · opened Sep 16, 2026

Environment

  • Claude Code version: 2.1.271 → reproduced again on 2.1.273 after auto-update
  • Client: VS Code extension, accessed via vscode.dev/tunnel/<host> (VS Code Remote Tunnels) to a headless Linux (NixOS) server
  • Account: personal Pro/Max subscription (not Team/Enterprise — so this is not the admin-toggle case)
  • Also reproduced identically from a plain integrated terminal on the same host running claude directly (not just inside the VS Code extension webview)

What happened

Starting Remote Control (/remote-control in the VS Code extension) surfaced:

Remote Control error: Claude.ai login was rejected — run /login, then /remote-control

Running /login (or a completely fresh claude process, or claude setup-token) goes through the browser OAuth consent screen successfully (Authorize works, browser is redirected with a valid-looking code+state in the query string), but the redirect target http://localhost:<port>/callback?code=...&state=... is unreachable from the browser (expected/documented behavior for SSH/remote-tunnel setups — browser and Claude Code process are on different machines).

Manually pasting code#state (or code=...&state=...) into the terminal's Paste code here if prompted > prompt — copied immediately from the address bar, no delay — consistently returns:

OAuth error: Request failed with status code 400
Press Enter to retry.

This reproduces:

  • With a fresh claude process each time (not just repeated "Enter to retry" — ruled out stale in-process PKCE state)
  • With claude setup-token as well as /login (ruled out this being specific to the Remote Control scope set — same 400 either way)
  • With the code pasted within seconds of being issued (ruled out code expiry)
  • With system clock verified accurate against an external time source (ruled out clock skew as the invalid_grant cause)
  • With no ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, DISABLE_TELEMETRY, DO_NOT_TRACK, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, or DISABLE_GROWTHBOOK set in the environment

An already-established login on the same machine (a long-running Claude Code session started earlier) continues to work fine — this only affects new OAuth token exchanges from this host.

Expected

Either the token exchange succeeds, or the terminal surfaces a specific reason for the 400 (expired/consumed code, PKCE mismatch, org policy, etc.) instead of a bare status code.

Additional context

The generic claude doctor (shell) diagnostic didn't surface anything related to this; it only reported an unrelated install/PATH note.

Happy to provide a debug log (--debug-file) or any other diagnostic on request.

View original on GitHub ↗

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