remote-control session permanently 401s after token refresh fails; /login cannot reach the process
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:
claude /loginin 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.
- Typing
/logininto the session's own input box on claude.ai — never reaches the process. The transcript shows no/loginbeing 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
- Run
claude remote-control(launchd agent) and open a session from claude.ai. - 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).
- Send a message →
401 OAuth access token has expired. - Run
claude /loginin a terminal; confirm the credential store is updated. - Send a message in that session again → still 401.
- Type
/loginin 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
/logintyped 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-cli2.1.271, desktop-bundled claude-code 2.1.270 - Claude Max subscription, OAuth login (not API key)
- Credentials in macOS Keychain;
~/.claude/.credentials.jsonwas present but empty (accessToken: "",expiresAt: 0) — possibly related, as the failing processes are theremote/ccd-cliones.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗