{"record":{"id":"5aef4b7fd6e31562","repo":"google-gemini/gemini-cli","slug":"failed-to-authenticate-with-user-code","errorCode":null,"errorMessage":"Failed to authenticate with user code.","messagePattern":"Failed to authenticate with user code\\.","errorType":"exception","errorClass":"FatalAuthenticationError","httpStatus":null,"severity":"critical","filePath":"packages/core/src/code_assist/oauth2.ts","lineNumber":298,"sourceCode":"        success = await authWithUserCode(client);\n        if (!success) {\n          writeToStderr(\n            '\\nFailed to authenticate with user code.' +\n              (i === maxRetries - 1 ? '' : ' Retrying...\\n'),\n          );\n        }\n      }\n    } finally {\n      exitAlternateScreen();\n      // If this was triggered from an active Gemini CLI TUI this event ensures\n      // the TUI will re-initialize the terminal state just like it will when\n      // another editor like VIM may have modified the buffer of settings.\n      coreEvents.emit(CoreEvent.ExternalEditorClosed);\n    }\n\n    if (!success) {\n      writeToStderr('Failed to authenticate with user code.\\n');\n      throw new FatalAuthenticationError(\n        'Failed to authenticate with user code.',\n      );\n    }\n\n    // Retrieve and cache Google Account ID after successful user code auth\n    try {\n      await fetchAndCacheUserInfo(client);\n    } catch (error) {\n      debugLogger.warn(\n        'Failed to retrieve Google Account ID during authentication:',\n        getErrorMessage(error),\n      );\n    }\n\n    await triggerPostAuthCallbacks(client.credentials);\n  } else {\n    // In ACP mode, we skip the interactive consent and directly open the browser\n    if (!config.getAcpMode()) {","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/core/src/code_assist/oauth2.ts#L280-L316","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  client = await getOauthClient(authType, config);\n} catch (e) {\n  if (e instanceof FatalAuthenticationError && e.message.includes('Failed to authenticate with user code')) {\n    // Retry with fresh codes or switch to browser-based auth\n    console.error('User code auth failed. Try browser-based login (unset NO_BROWSER).');\n    process.exit(2);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["oauth","authentication","user-code","fatal","retry-exhausted"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}