remote-control session permanently 401s after token refresh fails; /login cannot reach the process

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

What happened

A long-running session spawned by claude remote-control caches its OAuth credentials at process start. Once the in-memory access token expires and the refresh attempt fails, that session returns a 401 forever and there is no way to re-authenticate it in place.

The session transcript records, on every subsequent message:

"subtype": "api_error", "status": 401,
"formatted": "401 OAuth access token has expired. Re-authenticate to continue."
"retryAttempt": 1, "maxRetries": 10

The client UI then shows a banner telling the user to sign in again on their computer.

Why it is not recoverable

Two obvious recovery paths both fail:

  1. claude /login in a separate terminal — this succeeds and updates the credential store (I verified the new access token and a refresh token ~29 days out). The already-running session process never re-reads it. 401s continued 2 and 3 minutes after a successful login.
  1. Typing /login into the session's own input box on claude.ai — never reaches the process. The transcript shows no /login being received; while the "sign in again" banner is displayed, the UI appears to re-send the previously pending message instead of the new input. So the one slash command that could fix the session cannot be delivered to it.

The session process has no TTY (it is a child of ~/.claude/remote/srv/<hash>/server --serve, itself under launchd), so there is no terminal route to it either.

Only workaround found

Kill the remote-control agent and let launchd restart it. This works — the new agent picks up the current credentials — but every bridged claude.ai/code/session_* URL is destroyed, because new sessions get new IDs. In my case 14 sessions were lost this way; their transcripts survived on disk and had to be reopened individually with claude --resume <uuid>.

Impact

This is the normal remote workflow: work against the Mac from another machine (SSH / browser), come back later, continue. Instead, every bridged session becomes permanently unusable and the session URLs are lost. Transcripts are not lost, but the shared/bridged sessions are.

Steps to reproduce

  1. Run claude remote-control (launchd agent) and open a session from claude.ai.
  2. Leave it running long enough for the access token to expire and the refresh to fail (in my case the refresh token was itself near expiry).
  3. Send a message → 401 OAuth access token has expired.
  4. Run claude /login in a terminal; confirm the credential store is updated.
  5. Send a message in that session again → still 401.
  6. Type /login in that session's input box → not delivered; still 401.

Expected

  • Re-read the credential store when a request fails with 401 authentication_error, instead of retrying the same dead token 10 times.
  • At minimum, accept /login typed into a bridged session's input box, and preserve the session/bridge URL across a re-authentication.

Environment

  • macOS 15.6 (Darwin 25.6.0), Apple Silicon
  • Claude Code 2.1.268 (CLI), remote ccd-cli 2.1.271, desktop-bundled claude-code 2.1.270
  • Claude Max subscription, OAuth login (not API key)
  • Credentials in macOS Keychain; ~/.claude/.credentials.json was present but empty (accessToken: "", expiresAt: 0) — possibly related, as the failing processes are the remote/ccd-cli ones.

View original on GitHub ↗

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