-
Notifications
You must be signed in to change notification settings - Fork 10k
Description
Problem
Users report that after several hours of inactivity (especially after sleep/overnight), the Anthropic OAuth token expires and the refresh fails with a 400 error:
Error: Token refresh failed: 400
This forces users to re-login every morning or after periods of inactivity.
Related Issues:
- Claude subscription token expires after a period of time #6559 - Claude subscription token expires after a period of time
- Getting "Unauthorized: token expired" during conversation #4992 - Getting "Unauthorized: token expired" during conversation
Root Cause
Anthropic's OAuth refresh tokens appear to have a limited lifetime. When the access token expires and OpenCode attempts to refresh it, the refresh token itself may have already been invalidated by Anthropic's servers after extended periods of inactivity.
The current implementation only refreshes tokens reactively (when a request fails), rather than proactively keeping them alive.
Proposed Solution
Implement a token keep-alive mechanism that periodically pings all logged-in Anthropic OAuth accounts to prevent token expiration:
-
Use the existing
/api/oauth/usageendpoint - This endpoint:- Already exists in the codebase (
Auth.OAuthPool.fetchAnthropicUsage) - Requires authentication (keeps the token active)
- Does NOT consume any tokens or context
- Returns usage statistics (bonus: could be useful for UI)
- Already exists in the codebase (
-
Ping interval: Every 60 minutes
- First ping after 5 minutes (to let everything settle after startup)
- Then every hour while OpenCode is running
-
Multi-account support: Ping ALL logged-in Anthropic OAuth accounts
- Users with multiple accounts (Account 1, 2, 3, etc.) will have all accounts kept alive
- Only affects Anthropic provider (other providers like Copilot, OpenAI are not affected)
Implementation
New module: packages/opencode/src/auth/keepalive.ts
// Pings all Anthropic OAuth accounts every hour
// Uses /api/oauth/usage endpoint (no token cost)
// Logs success/failure for debuggingIntegrated into InstanceBootstrap() so it starts automatically when OpenCode runs.
Benefits
- No more morning re-logins - Tokens stay fresh as long as OpenCode is running
- Zero cost - Uses usage endpoint, no tokens consumed
- Multi-account friendly - All accounts stay active
- Non-intrusive - Runs in background, logged for debugging
- Automatic - No user action required
Testing
- Run OpenCode for extended periods
- Monitor logs for
auth.keepalivemessages - Verify tokens remain valid after previously problematic timeframes