fix(core): prevent silent hang during OAuth auth on headless Linux#26571
Conversation
|
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. |
Summary of ChangesHello, 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 addresses a silent hang issue occurring on headless Linux environments (such as WSL, SSH, or Docker) when using the Gemini CLI. The deadlock was caused by an un-timed-out probe of the OS keychain during startup. By optimizing the authentication flow to skip unnecessary keychain checks and adding a timeout mechanism to the keychain probe, the CLI now gracefully falls back to file-based storage instead of hanging indefinitely. Highlights
Using Gemini Code AssistThe 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
Customization To customize the 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 Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. 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. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request optimizes the createContentGeneratorConfig function by deferring API key loading until after authentication checks, preventing unnecessary keychain access. Additionally, it introduces a 2-second timeout for the keychain functional probe in KeychainService to prevent the CLI from hanging on headless Linux environments. I have no feedback to provide as there were no review comments.
createContentGeneratorConfig eagerly awaits loadApiKey() even when the caller has selected LOGIN_WITH_GOOGLE / COMPUTE_ADC and the result is unused. That call walks into HybridTokenStorage → KeychainService, which on Linux probes libsecret (Secret Service over D-Bus). On environments without a running Secret Service (WSL, SSH sessions without DISPLAY, Docker, CI), the probe does not return: keytar's setPassword/getPassword cycle blocks indefinitely and the CLI hangs with no output, before anything is rendered or logged. Two fixes: 1. Move the LOGIN_WITH_GOOGLE / COMPUTE_ADC early-return above the API key load so OAuth users never touch the keychain. The eager load was wasted work for those auth types regardless. 2. Wrap the keychain functional probe in Promise.race against a 2s timeout, mirroring the spirit of the existing macOS pre-check. If the Secret Service is unresponsive, the CLI now falls back to FileKeychain instead of stalling forever. Other code paths that hit the keychain (MCP token storage, manual API key save) get the same safety net. Repro before the fix: on WSL with no D-Bus session and selectedType set to oauth-personal, run `gemini -p hi`. The process produces zero output and never exits. After: it reaches the OAuth user-code prompt within ~2s.
11a59c7 to
eb4cba3
Compare
scidomino
left a comment
There was a problem hiding this comment.
Looks good but for one nit. Please fix and I will approve.
Per review feedback: encapsulate the 2s timeout inside the probe method itself rather than wrapping it at the call site. Same behavior, but the timeout is now a property of the functional check rather than something each caller has to remember to apply.
Gemini CLI was hanging in my environment, tested these changes and they fixed it for me.
AI generated summary below:
=====
Summary
On headless Linux (WSL, SSH-without-DISPLAY, Docker, CI),
geminihangs silently with no output and never exits when the user has selectedoauth-personalauth and there are no cached credentials. There is no error, no log line, no debug output — the process is just deadlocked early in startup, well before the TUI mounts or--debugcould help.Root cause is two compounding issues:
createContentGeneratorConfigeagerly awaitsloadApiKey()for every auth type — evenLOGIN_WITH_GOOGLE/COMPUTE_ADC, where the resultinggeminiApiKeyis unused (the function returns at the early branch).loadApiKey()goes throughHybridTokenStorage→KeychainService, which performs a synchronous-looking probe of the OS keychain.The keychain functional probe has no timeout on Linux. On macOS there is an explicit
security default-keychainpre-check (isMacOSKeychainAvailable, lines 193–220) specifically to avoid blocking popups. Linux gets no equivalent.keytar.setPassword→ libsecret → D-Bus → Secret Service: if no Secret Service is running (typical in WSL/SSH/Docker/CI), the call hangs indefinitely. There is no logging at this layer, hence the silent hang.Repro
Workaround that confirms the cause: setting
GEMINI_FORCE_FILE_STORAGE=true(skips the keytar probe) immediately makesgeminiproduce its real error output instead of hanging.Fix
1. Skip the API-key load for auth types that don't need it.
createContentGeneratorConfigreturned early forLOGIN_WITH_GOOGLE/COMPUTE_ADCafter awaitingloadApiKey(). Move the early-return above the load — these auth types never readgeminiApiKey, so the work was always wasted, and avoiding it sidesteps the keychain entirely on the OAuth happy path.2. Bound the keychain functional probe with a timeout.
Promise.racetheset/get/deletecycle against a 2s timeout. If the Secret Service doesn't respond, fall back toFileKeychainrather than blocking forever. This mirrors the spirit of the existing macOS pre-check and protects every other code path that hits the keychain (MCP token storage, manual API key save, etc.).Impact
FileKeychain, instead of an infinite hang.