google-gemini/gemini-cli · critical · FatalAuthenticationError

Manual authorization is required but the current session is

Error message

Manual authorization is required but the current session is non-interactive. Please run the Gemini CLI in an interactive terminal to log in, provide a GEMINI_API_KEY, or ensure Application Default Credentials are configured.

What it means

Thrown as a FatalAuthenticationError when browser launch is suppressed (NO_BROWSER=true or equivalent) AND the current session is non-interactive (no TTY). In this state the OAuth flow requires manual authorization (the user must open a URL and paste a code), but there is no terminal to display the prompt. The error lists three alternative auth methods: run interactively, set GEMINI_API_KEY, or configure Application Default Credentials.

Source

Thrown at packages/core/src/code_assist/oauth2.ts:262

        // the service account email.
      });
      await computeClient.getAccessToken();
      debugLogger.log('Authentication successful.');

      // Do not cache creds in this case; note that Compute client will handle its own refresh
      return computeClient;
    } catch (e) {
      throw new Error(
        `Could not authenticate using metadata server application default credentials. Please select a different authentication method or ensure you are in a properly configured environment. Error: ${getErrorMessage(
          e,
        )}`,
      );
    }
  }

  if (config.isBrowserLaunchSuppressed()) {
    if (!config.isInteractive()) {
      throw new FatalAuthenticationError(
        'Manual authorization is required but the current session is non-interactive. ' +
          'Please run the Gemini CLI in an interactive terminal to log in, ' +
          'provide a GEMINI_API_KEY, or ensure Application Default Credentials are configured.',
      );
    }
    let success = false;
    const maxRetries = 2;
    // Enter alternate buffer
    enterAlternateScreen();
    // Clear screen and move cursor to top-left.
    writeToStdout('\u001B[2J\u001B[H');
    disableMouseEvents();
    disableKittyKeyboardProtocol();
    enableLineWrapping();

    try {
      for (let i = 0; !success && i < maxRetries; i++) {
        success = await authWithUserCode(client);

View on GitHub (pinned to 5024443c72)

Solutions

  1. Set GEMINI_API_KEY environment variable for non-interactive, non-browser authentication.
  2. Configure Application Default Credentials: run 'gcloud auth application-default login' on a machine with a browser, then copy the credentials.
  3. Run the CLI in an interactive terminal with a TTY and without NO_BROWSER set to complete OAuth once.
  4. If in a container, use 'docker run -it' to allocate a TTY.
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight check: can we authenticate in this environment?
function canAuthenticateNonInteractively(config: Config): boolean {
  if (process.env['GEMINI_API_KEY']) return true;
  // Check for ADC file existence
  const adcPath = path.join(process.env['CLOUDSDK_CONFIG'] ?? path.join(homedir(), '.config', 'gcloud'), 'application_default_credentials.json');
  return fsSync.existsSync(adcPath);
}

if (config.isBrowserLaunchSuppressed() && !config.isInteractive()) {
  if (!canAuthenticateNonInteractively(config)) {
    throw new Error('Non-interactive session needs GEMINI_API_KEY or ADC configured.');
  }
}

Try / catch

try {
  client = await getOauthClient(authType, config);
} catch (e) {
  if (e instanceof FatalAuthenticationError && e.message.includes('non-interactive')) {
    // Provide guidance and exit gracefully
    console.error('Set GEMINI_API_KEY or run in an interactive terminal.');
    process.exit(2);
  }
  throw e;
}

Prevention

When it happens

Trigger: config.isBrowserLaunchSuppressed() returns true (NO_BROWSER env var set) and config.isInteractive() returns false (stdin is not a TTY). The code checks both conditions before attempting the user-code auth flow and throws immediately since the flow cannot proceed.

Common situations: Running the CLI in a CI/CD pipeline, Docker container, SSH session without TTY allocation, or cron job where NO_BROWSER is set and there's no interactive terminal; a headless server deployment; piping stdin from another process making the session non-interactive.

Related errors


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