google-gemini/gemini-cli · critical · FatalAuthenticationError
Failed to authenticate with user code.
Error message
Failed to authenticate with user code.
What it means
Thrown as a FatalAuthenticationError after the user-code-based OAuth flow fails all retry attempts. The code enters an alternate screen buffer, clears the terminal, and attempts authWithUserCode() up to maxRetries (2) times. If none succeed, it writes a failure message to stderr and throws this fatal error. authWithUserCode typically involves the user navigating to a URL and entering a code; failure means the code was wrong, expired, or the token exchange failed.
Source
Thrown at packages/core/src/code_assist/oauth2.ts:298
success = await authWithUserCode(client);
if (!success) {
writeToStderr(
'\nFailed to authenticate with user code.' +
(i === maxRetries - 1 ? '' : ' Retrying...\n'),
);
}
}
} finally {
exitAlternateScreen();
// If this was triggered from an active Gemini CLI TUI this event ensures
// the TUI will re-initialize the terminal state just like it will when
// another editor like VIM may have modified the buffer of settings.
coreEvents.emit(CoreEvent.ExternalEditorClosed);
}
if (!success) {
writeToStderr('Failed to authenticate with user code.\n');
throw new FatalAuthenticationError(
'Failed to authenticate with user code.',
);
}
// Retrieve and cache Google Account ID after successful user code auth
try {
await fetchAndCacheUserInfo(client);
} catch (error) {
debugLogger.warn(
'Failed to retrieve Google Account ID during authentication:',
getErrorMessage(error),
);
}
await triggerPostAuthCallbacks(client.credentials);
} else {
// In ACP mode, we skip the interactive consent and directly open the browser
if (!config.getAcpMode()) {View on GitHub (pinned to 5024443c72)
Solutions
- Retry the login flow, carefully copying the verification code from the URL.
- Ensure the system clock is accurate (NTP synced) to avoid token validation failures.
- Check network connectivity to accounts.google.com.
- If the code consistently fails, switch to browser-based auth (unset NO_BROWSER) or use GEMINI_API_KEY.
Defensive patterns
Strategy: retry
Try / catch
try {
client = await getOauthClient(authType, config);
} catch (e) {
if (e instanceof FatalAuthenticationError && e.message.includes('Failed to authenticate with user code')) {
// Retry with fresh codes or switch to browser-based auth
console.error('User code auth failed. Try browser-based login (unset NO_BROWSER).');
process.exit(2);
}
throw e;
} Prevention
- Carefully copy the verification code from the URL when using the user-code flow.
- Ensure system clock is NTP-synced to avoid token validation issues.
- Complete the consent flow promptly before codes expire.
- Prefer browser-based OAuth when a browser is available.
When it happens
Trigger: The NO_BROWSER path is active; authWithUserCode(client) returns false twice (maxRetries = 2). Each attempt asks the user to open a URL manually, enter a verification code, and complete consent. Returning false indicates the OAuth handshake did not complete — wrong code, expired code, network error during token exchange, or user abandon.
Common situations: User enters an incorrect or expired verification code both times; the OAuth callback server fails to receive the redirect; network issues prevent token exchange; the user closes the browser or navigates away before completing consent; system clock skew causes token validation to fail.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Manual authorization is required but the current session is
- Authentication cancelled by user.
- Failed to open browser: ${getErrorMessage(err)}
- ${originalMessage}. The initial COMPUTE_ADC attempt also fai
- COMPUTE_ADC failed: ${adcMessage}. (LOGIN_WITH_GOOGLE fallba
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/5aef4b7fd6e31562.
Report an issue: GitHub.