Skip to content

fix(core): avoid keep-alive socket reuse during OAuth token exchange#28103

Open
ryium wants to merge 1 commit into
google-gemini:mainfrom
ryium:fix/oauth-keepalive-premature-close
Open

fix(core): avoid keep-alive socket reuse during OAuth token exchange#28103
ryium wants to merge 1 commit into
google-gemini:mainfrom
ryium:fix/oauth-keepalive-premature-close

Conversation

@ryium

@ryium ryium commented Jun 23, 2026

Copy link
Copy Markdown

Summary

OAuth "Sign in with Google" fails on Node.js >= 24.17.0 with
Failed to exchange authorization code for tokens: ... Premature close.
A Node http.Agent socket-reuse regression makes node-fetch throw a spurious
ERR_STREAM_PREMATURE_CLOSE when a pooled keep-alive socket is reused, breaking
login for everyone on current Node. This change makes the OAuth token exchange
use a fresh (non-keep-alive) connection so sign-in works again without
downgrading Node.

Details

The token exchange runs through google-auth-librarygaxiosnode-fetch,
which uses Node's global keep-alive agent. On Node >= 24.17.0 the "fix response
queue poisoning in http.Agent" change exposes a reuse race that surfaces as a
false "Premature close" (see nodejs/node#63989). This matches reports that
downgrading to Node 20 makes login work again.

Fix: in initOauthClient (packages/core/src/code_assist/oauth2.ts), pass
new https.Agent({ keepAlive: false }) to the OAuth2Client transporter when no
proxy is configured, forcing a fresh connection per request and avoiding the
poisoned-socket reuse. The proxy path is left unchanged, since supplying our own
agent would make gaxios ignore the configured proxy. Because the same client
also backs the Code Assist API calls, the whole code-assist flow benefits.

Related Issues

How to Validate

  1. Use Node.js >= 24.17.0 (node -v).
  2. Build core: npm run generate && npm run build --workspace=@google/gemini-cli-core.
  3. Run the unit tests: npx vitest run packages/core/src/code_assist/oauth2.test.ts
    • New cases assert the OAuth transporter uses a keepAlive: false agent when
      no proxy is set, and keeps proxy (no custom agent) when a proxy is set.
  4. End-to-end: launch the CLI and choose "Login with Google"; the
    authorization-code → token exchange completes instead of failing with
    "Premature close".
  5. Edge case (proxy): with HTTPS_PROXY set / --proxy configured, login still
    routes through the proxy as before.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

On Node >= 24.17.0 a regression in http.Agent socket reuse ("fix response queue poisoning") makes node-fetch throw a spurious ERR_STREAM_PREMATURE_CLOSE ("Premature close") when a pooled keep-alive socket is reused. This broke "Sign in with Google": the authorization-code -> token exchange goes through google-auth-library -> gaxios -> node-fetch over Node's global keep-alive agent.

Pass an agent with keepAlive: false to the OAuth2Client transporter when no proxy is configured, so each request uses a fresh connection and avoids the poisoned-socket race. The same client backs the Code Assist API calls, so the whole flow is covered. The proxy path is left unchanged because passing our own agent would make gaxios ignore the proxy.

Refs nodejs/node#63989, google-gemini#28072, google-gemini#26411
@ryium ryium requested a review from a team as a code owner June 23, 2026 02:22
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 critical regression in Node.js versions 24.17.0 and later, where socket reuse in the global http.Agent causes OAuth token exchange failures. By forcing a fresh connection per request via a custom https.Agent when no proxy is configured, the fix restores login functionality for users on newer Node.js versions while maintaining support for existing proxy environments.

Highlights

  • OAuth Connection Fix: Implemented a workaround for a Node.js regression (>= 24.17.0) that caused 'ERR_STREAM_PREMATURE_CLOSE' errors during OAuth token exchange by disabling keep-alive for non-proxy connections.
  • Proxy Compatibility: Ensured that existing proxy configurations remain functional by only applying the custom agent when no proxy is detected, preventing gaxios from ignoring proxy settings.
  • Regression Testing: Added unit tests to verify that the OAuth transporter correctly disables keep-alive when no proxy is present and preserves proxy settings when configured.
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 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 .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 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

  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.

@github-actions github-actions Bot added the size/m A medium sized PR label Jun 23, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/M

  • Lines changed: 89
  • Additions: +86
  • Deletions: -3
  • Files changed: 2

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

Copy link
Copy Markdown
Contributor

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 introduces a workaround for a Node.js regression (nodejs/node#63989) where socket reuse in http.Agent causes node-fetch to throw a spurious ERR_STREAM_PREMATURE_CLOSE error during OAuth token exchange. To resolve this, HTTP keep-alive is disabled by configuring a custom https.Agent with keepAlive: false when initializing the OAuth2Client, unless a proxy is configured. Corresponding unit tests have been added to verify this behavior under both proxy and non-proxy configurations. There are no review comments, so I have no feedback to provide.

@gemini-cli gemini-cli Bot added priority/p2 Important but can be addressed in a future release. area/security Issues related to security labels Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/security Issues related to security priority/p2 Important but can be addressed in a future release. size/m A medium sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant