OAuth credentials silently wiped on failed token refresh — long-running agents lose auth

Resolved 💬 3 comments Opened Mar 1, 2026 by chrissyhurleyr2d2 Closed Mar 5, 2026

Description

Long-running Claude Code agents (persistent tmux sessions that run 24/7) are losing their OAuth authentication every ~12 hours. On restart, the session shows "Not logged in" even though the keychain entry Claude Code-credentials exists.

Root cause investigation

On the affected machine (macOS, Claude Code 2.1.63):

  1. The Claude Code-credentials keychain entry exists but contains empty data
  2. The entry's cdat (creation date) shows it was recreated today — suggesting the original valid credential was deleted and replaced with an empty one
  3. The keychain is set to no-timeout and was confirmed unlocked at the time
  4. The machine does not sleep (pmset sleep = 0)

Theory: When the OAuth token expires, Claude Code attempts a refresh. If the refresh fails (network blip, server error, etc.), the old credential is deleted/overwritten with an empty value instead of being preserved. This leaves the agent in a state where:

  • The keychain entry exists (so no "missing credential" error)
  • But the entry is empty (so auth fails silently)
  • The only recovery is a full manual re-login via browser OAuth flow

Expected behavior

  • If a token refresh fails, the existing valid credential should be preserved (not overwritten with empty data)
  • If the credential becomes invalid, a clear error message should be logged (not silent failure)
  • Ideally, Claude Code should retry the refresh before giving up

Environment

  • Claude Code version: 2.1.63
  • OS: macOS (Darwin 25.2.0) on Mac Mini
  • Auth method: OAuth (browser flow via /login)
  • Usage pattern: Persistent tmux session, watchdog auto-restart, running 24/7
  • 3 agents on 3 separate machines all running the same version — issue observed on one so far

Impact

For autonomous agents that run unattended, this is a hard failure that requires human intervention (browser OAuth flow). It's particularly disruptive because:

  • The agent appears to start normally but can't make any API calls
  • No error is logged until the agent tries to do work
  • The human may not notice for hours

Workaround

Currently: human manually completes the /login OAuth flow when detected.

Suggested: store an API key as a fallback auth method so the agent can self-recover when OAuth expires.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗