Skip to content

Conversation

@JuanCS-Dev
Copy link

Fixes #13853

Description

Fixes regression in v0.18.0 where authentication URL was not visible in headless environments (SSH/Docker), causing the CLI to hang indefinitely during login.

Root Cause

The commit bdf80ea (#13600) introduced stdout/stderr patching that prevented the auth URL from being displayed in non-interactive environments.

Changes

  1. Write auth URL directly to stderr using writeToStderr() to bypass stdio patching
  2. Remove fatal error throw when browser fails to open - allow manual authentication
  3. Improve error messages to reference the URL displayed above
  4. Add explicit stderr writes for all auth-related messages

Testing

  • Build passes: npm run build
  • Should be tested in headless environment (SSH/Docker)
  • URL should now be visible even when browser fails to open

Impact

  • Restores v0.17.1 behavior where URL was always visible
  • Allows authentication in headless environments
  • Non-breaking change for interactive environments

@JuanCS-Dev JuanCS-Dev requested a review from a team as a code owner November 26, 2025 19:50
@google-cla
Copy link

google-cla bot commented Nov 26, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @JuanCS-Dev, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical regression in version 0.18.0 that prevented the authentication URL from being displayed in headless environments, leading to an indefinite hang during login. The fix ensures that the authentication URL and related messages are always visible by writing them directly to "stderr", bypasses fatal errors when the browser fails to launch, and improves user guidance, thereby restoring seamless authentication for all environments.

Highlights

  • Auth URL Visibility: Ensured the authentication URL is always visible, particularly in headless environments (SSH/Docker), by writing it directly to "stderr" to bypass stdout/stderr patching.
  • Error Handling: Removed the "FatalAuthenticationError" when the browser fails to open, allowing users to complete authentication manually using the provided URL.
  • Improved User Feedback: Enhanced error messages related to browser opening failures to explicitly reference the authentication URL, guiding users to manual authentication.
  • Consistent Output: Implemented explicit "stderr" writes for all authentication-related messages, ensuring consistent visibility across different environments.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses the authentication issue in headless environments by ensuring the authentication URL is always visible. Writing auth-related messages directly to stderr is a good solution to bypass stdio patching. Removing the fatal error when the browser fails to open is a great improvement, as it allows for manual authentication and makes the CLI more robust in various environments. I've identified one area for improvement regarding code duplication in error handling, which I've detailed in a specific comment. Overall, these are solid changes that improve the user experience for authentication.

Comment on lines 264 to 285
childProcess.on('error', (error) => {
const errorMsg =
`Failed to open browser with error: ${getErrorMessage(error)}\n` +
`Please visit the URL above or run again with NO_BROWSER=true set.\n`;
writeToStderr(errorMsg);
coreEvents.emit(CoreEvent.UserFeedback, {
severity: 'error',
message:
`Failed to open browser with error: ${getErrorMessage(error)}\n` +
`Please try running again with NO_BROWSER=true set.`,
message: errorMsg,
});
});
} catch (err) {
const errorMsg =
`Failed to open browser with error: ${getErrorMessage(err)}\n` +
`Please visit the URL above or run again with NO_BROWSER=true set.\n`;
writeToStderr(errorMsg);
coreEvents.emit(CoreEvent.UserFeedback, {
severity: 'error',
message:
`Failed to open browser with error: ${getErrorMessage(err)}\n` +
`Please try running again with NO_BROWSER=true set.`,
message: errorMsg,
});
throw new FatalAuthenticationError(
`Failed to open browser: ${getErrorMessage(err)}`,
);
// Don't throw here - let the user complete auth manually via the URL
// The loginCompletePromise will handle timeout if auth never completes
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The error handling logic for when open fails is duplicated in the childProcess.on('error', ...) handler and the catch (err) block. This can lead to maintenance issues where one is updated but the other is forgotten. To improve maintainability and ensure consistency, this logic should be extracted into a single helper function.

      const handleBrowserOpenError = (error: unknown) => {
        const errorMsg =
          `Failed to open browser with error: ${getErrorMessage(error)}\n` +
          `Please visit the URL above or run again with NO_BROWSER=true set.\n`;
        writeToStderr(errorMsg);
        coreEvents.emit(CoreEvent.UserFeedback, {
          severity: 'error',
          message: errorMsg,
        });
      };
      childProcess.on('error', handleBrowserOpenError);
    } catch (err) {
      handleBrowserOpenError(err);
      // Don't throw here - let the user complete auth manually via the URL
      // The loginCompletePromise will handle timeout if auth never completes
    }

- Write auth URL directly to stderr using writeToStderr to bypass stdio patching
- Don't throw error when browser fails to open, allow manual auth completion
- Improves error messages to reference the URL shown above
- Fixes regression where URL was not visible in v0.18.0 headless environments

Fixes google-gemini#13853
@KazenDev
Copy link

Thanks for the quick turnaround on this, @JuanCS-Dev !!

Since I have the exact headless environment (Ubuntu VPS via SSH) where the regression was originally found, I'm available to verify/test this fix immediately to ensure it works as expected.

Is there a preferred way you'd like me to test this PR (e.g., pulling this specific branch and building locally) or should I wait for a nightly build?

@JuanCS-Dev JuanCS-Dev force-pushed the fix-headless-auth-13853 branch from 755c486 to 4798eca Compare November 26, 2025 21:14
@SandyTao520
Copy link
Collaborator

This is already fixed in main by #13565 Fix multiple bugs with auth flow including using the implemented but unused restart support. Please let me know if it still happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] v0.18.0 Regression: CLI hangs on login in headless environments (no auth URL fallback)

4 participants