[BUG] macOS DarkWake: transient DNS failure during OAuth refresh loses login
Preflight checklist
- [x] I searched existing issues and did not find this exact failure mode.
- [x] This reproduces on the current native Claude Code release.
- [x] This report contains no tokens or account identifiers.
What's wrong?
Claude Code repeatedly loses its Claude.ai OAuth login after macOS sleep and requires a browser /login again.
Local telemetry shows OAuth refresh attempts occurring during macOS DarkWake while DNS is not yet usable. Those attempts fail with ENOTFOUND or ETIMEDOUT. Afterward, Claude reports loggedIn: false, and the Claude Code-credentials Keychain item is absent. Running /login recreates it and immediately restores normal operation.
This happened 9 times in 8 days. The fresh OAuth credential has an 8-hour access-token lifetime and a roughly 28-day refresh-token lifetime, so daily interactive login is not expected expiry.
What should happen?
A transient network or DNS failure during token refresh must not invalidate, delete, or replace the existing refresh credential. Claude Code should retain the credential and retry after the machine is fully awake and network reachability returns.
Only a definitive OAuth response such as revocation or invalid_grant should end the session.
Evidence
Claude telemetry contains 19 tengu_oauth_token_refresh_failure events:
- 18 x
ENOTFOUND - 1 x
ETIMEDOUT - 2 from the TypeScript SDK entrypoint and 17 from the CLI entrypoint
- Refresh-lock starting/acquiring/acquired/releasing/released counts are all exactly 19, so the lock path completed each time.
One directly correlated timeline (UTC event times, local macOS power-log times):
2026-08-02 10:49:16 +0200 DarkWake from Deep Idle (2-second SleepService window)
2026-08-02T08:49:16.723Z OAuth refresh failure: ENOTFOUND
2026-08-02T08:49:18.735Z OAuth refresh retry failure: ENOTFOUND
2026-08-02T08:49:18.801Z OAuth refresh retry failure: ENOTFOUND
2026-08-02 10:49:18 +0200 Sleep Service Back to Sleep
Foreground symptom:
Not logged in - Please run /login
Other recorded failures also align with maintenance/DarkWake windows.
Steps to reproduce
- Log into Claude Code using a Claude.ai subscription.
- Leave a Claude Code CLI or SDK session alive.
- Let the 8-hour access token approach expiration.
- Put the Mac to sleep and allow a maintenance DarkWake while DNS/network is not fully available.
- Claude attempts OAuth refresh and receives
ENOTFOUNDor a timeout. - Wake the Mac normally and run Claude Code or
claude auth status --json. - Claude is logged out and requires
/login; the prior refresh token should still have weeks of validity.
The exact timing makes this awkward to reproduce on demand, but the power log and Claude telemetry establish the sequence.
Environment
- Claude Code 2.1.224, native installation, commit
8a2a469b68f9 - macOS 26.6 (25G72), Apple Silicon
- Authentication: Claude.ai Max subscription
- Both CLI and TypeScript SDK entrypoints observed
- No
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN,CLAUDE_CODE_OAUTH_TOKEN,CLAUDE_CONFIG_DIR, or host-credentials override - No system or shell proxy
- Login Keychain is unlocked and has no automatic lock timeout
claude doctorreports no installation problem- DNS and OAuth work normally once the machine is fully awake
Additional context
This appears distinct from concurrent refresh races: every recorded refresh attempt acquired and released Claude's refresh lock. It also differs from a permanently broken DNS or proxy configuration because normal foreground networking succeeds.
Possibly related reports include #54443, #24317, #60104, #77187, and #80072, but none describes a transient DarkWake DNS failure followed by loss of a still-valid refresh credential.
The important data-safety fix is to preserve the existing refresh token on ENOTFOUND/ETIMEDOUT, wait for network reachability, and retry after wake.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗