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
- Set GEMINI_API_KEY environment variable for non-interactive, non-browser authentication.
- Configure Application Default Credentials: run 'gcloud auth application-default login' on a machine with a browser, then copy the credentials.
- Run the CLI in an interactive terminal with a TTY and without NO_BROWSER set to complete OAuth once.
- 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
- Always set GEMINI_API_KEY in CI/CD and headless environments.
- Run 'gcloud auth application-default login' once on a machine with a browser.
- Use 'docker run -it' to allocate a TTY for interactive OAuth in containers.
- Detect non-interactive environments early and switch auth strategy.
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
- Failed to open browser: ${getErrorMessage(err)}
- Failed to authenticate with user code.
- Authentication cancelled by user.
- ${originalMessage}. The initial COMPUTE_ADC attempt also fai
- Failed to load OAuth credentials
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/2fa3eebfbcb8a74f.
Report an issue: GitHub.