OAuth token refresh produces tokens with missing scopes, causing repeated 403 and re-login prompts
Bug Description
After a token refresh cycle, Claude Code sometimes ends up with an OAuth access token that is missing required scopes (specifically user:profile). The token passes the local expiration check ("OAuth token check complete") but every subsequent API call fails with HTTP 403:
OAuth token does not meet scope requirement user:profile
OAuth token does not meet scope requirement any_of(user:profile, user:office)
The user is forced to manually run /login to do a full OAuth flow, which grants the correct scopes. This happens repeatedly — every time the token expires and refreshes, it may come back without the required scopes.
Environment
- Claude Code version: 2.1.76 (latest)
- OS: Windows 11 (MINGW64/Git Bash)
- Subscription: Max
Steps to Reproduce
- Log in via
/login— works fine, token has all scopes includinguser:profile - Wait for token to expire (~8 hours)
- On next Claude Code launch, token refresh runs silently
- Refreshed token passes local expiration check but is missing
user:profilescope - All API calls fail with 403
- User must manually
/loginagain
Evidence from Debug Logs
The debug logs show the pattern clearly — token check passes, but API calls immediately fail:
[DEBUG] [API:auth] OAuth token check starting
[DEBUG] [API:auth] OAuth token check complete
[ERROR] AxiosError: [url=https://api.anthropic.com/api/oauth/claude_cli/client_data,status=403,body=OAuth token does not meet scope requirement user:profile]
[ERROR] AxiosError: [url=https://api.anthropic.com/api/oauth/profile,status=403,body=OAuth token does not meet scope requirement any_of(user:profile, user:office)]
These 403 errors repeat on every API call until the user manually re-authenticates.
Current token scopes (after fresh /login):user:file_upload, user:inference, user:mcp_servers, user:profile, user:sessions:claude_code
Expected Behavior
Token refresh should either:
- Request all required scopes when refreshing the access token
- Detect the 403 scope mismatch and automatically trigger a full re-auth flow instead of silently failing
Workaround
Manual /login each time the token expires. On Windows this is a single button click but still disruptive.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗