[BUG] VS Code extension prompts re-login on every PC restart when access token is expired at startup
Summary
The Claude Code VS Code extension forces a full re-login after every PC restart. The root cause is a startup race between the extension's OAuth token refresh and the network becoming available: the access token is expired (short-lived, ~24 hours), the extension attempts to refresh it immediately at startup, the refresh request fails (network not yet up), and rather than retrying with backoff the extension immediately falls through to prompting the user to log in again.
Auth mode: Claude.ai OAuth / Max subscription (not API-key billing)
Environment
- Claude Code VS Code extension version:
2.1.177 - Install path:
~/.vscode-server/extensions/anthropic.claude-code-2.1.177-linux-x64 - OS: Ubuntu 24.04, Linux 6.8.0, x86_64
- VS Code mode: VS Code Server (
~/.vscode-server/) - gnome-keyring: not installed (not the cause — credentials are stored in
~/.claude/.credentials.json, not the system keychain)
What Happens
- PC reboots
- VS Code Server starts and loads the Claude Code extension
- The locally stored access token in
~/.claude/.credentials.jsonhas expired (access tokens are short-lived, ~24 hours based on observedexpiresAtvalues) - The extension calls
refreshOAuthToken()to get a new token - The refresh HTTP request fails — likely because the network stack isn't fully up at the time VS Code Server initializes
- The extension logs
"Token refresh failed"and returnsnull - User is prompted to log in again
Confirmed via source inspection
Inspected extension.js in the installed extension. The relevant path in getAuthHeaders():
if (c0e(e.expiresAt)) {
// token expired or expiring soon
let r = await this.refreshOAuthToken(e);
if (r) return { Authorization: `Bearer ${r.accessToken}`, ... };
// refresh returned null → falls through
this.logger.warn("failed, using potentially expired token");
// ... but this expired token causes auth failure → login prompt
}
refreshOAuthToken() makes a single attempt with no retry/backoff:
if (n.status !== 200) {
this.logger.error(`Token refresh failed: ${n.statusText}`);
return null; // ← triggers re-login prompt
}
Workaround
Run claude --version in a terminal before opening VS Code after a reboot. The CLI refreshes the token and writes updated credentials to ~/.claude/.credentials.json. VS Code then finds a valid token on startup.
Expected Behavior
The extension should retry the refresh request with exponential backoff (e.g., 3 attempts over ~10 seconds) before giving up and prompting for login. A startup network race should not require the user to re-authenticate via browser.
Related Issues
- #54443 — OAuth refresh returns 400 (different failure mode: server-side rejection, not startup network race)
- #47754 — Cloudflare WAF blocking refresh on headless Linux servers