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

  1. Retry the login flow, carefully copying the verification code from the URL.
  2. Ensure the system clock is accurate (NTP synced) to avoid token validation failures.
  3. Check network connectivity to accounts.google.com.
  4. 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

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

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/5aef4b7fd6e31562. Report an issue: GitHub.