Fix Gemini OAuth refresh when CLI oauth2.js is missing#1984
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 7:19 AM ET / 11:19 UTC. Summary Reproducibility: yes. Current-main source has a deterministic missing-client failure for expired tokens, and the PR body provides redacted live runs showing successful refresh through both new discovery paths. Review metrics: 3 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the owner-refined explicit-first resolver after exact-head checks pass, retaining the fixture coverage and documented recovery options for affected Workspace and education accounts. Do we have a high-confidence way to reproduce the issue? Yes. Current-main source has a deterministic missing-client failure for expired tokens, and the PR body provides redacted live runs showing successful refresh through both new discovery paths. Is this the best way to solve the issue? Yes. Explicit credentials first, installed CLI discovery next, and bounded known-path fallback directly repair the compatibility failure without adding automatic provider switching or a competing usage source. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 98de97833505. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (7 earlier review cycles)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62115c1624
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| setenv("GEMINI_OAUTH_CLIENT_ID", "env-client-id", 1) | ||
| setenv("GEMINI_OAUTH_CLIENT_SECRET", "env-client-secret", 1) |
There was a problem hiding this comment.
Isolate OAuth env overrides across suites
Because the resolver now checks GEMINI_OAUTH_CLIENT_ID/GEMINI_OAUTH_CLIENT_SECRET before the fake Gemini CLI, these process-wide overrides can bleed into other Gemini fetch tests while Swift Testing runs suites in parallel. @Suite(.serialized) only orders tests inside this suite, so a concurrent GeminiStatusProbeAPITests case that installs a fake CLI and expects test-client-id can intermittently send env-client-id instead; isolate the OAuth client via injection or serialize all suites that mutate these globals.
Useful? React with 👍 / 👎.
| "/opt/homebrew/lib/node_modules/@google/gemini-cli-core/\(oauthFile)", | ||
| "/opt/homebrew/lib/\(nestedOAuthFile)", | ||
| "/usr/local/lib/node_modules/@google/gemini-cli-core/\(oauthFile)", | ||
| "/usr/local/lib/\(nestedOAuthFile)", |
There was a problem hiding this comment.
Cover the real Homebrew formula layout
When Gemini is installed by Homebrew but the app cannot resolve /opt/homebrew/bin/gemini or /usr/local/bin/gemini from its captured PATH, this fallback still misses the credentials: the repo's Homebrew fixture models the package under Cellar/.../libexec/lib/node_modules/@google/gemini-cli/bundle, while these newly added probes only look under lib/node_modules. In that common Homebrew scenario the recovery path still falls through to the missing-config error, so add the Homebrew binary paths to discovery or probe the Cellar/libexec layout here.
Useful? React with 👍 / 👎.
|
@clawsweeper re-review CI is fully green on |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review Addressed the review rank-up items on
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20e709312b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| let binURL = try env.writeFakeGeminiCLI(includeOAuth: false) | ||
| let previousGeminiPath = ProcessInfo.processInfo.environment["GEMINI_CLI_PATH"] | ||
| setenv("GEMINI_CLI_PATH", binURL.path, 1) |
There was a problem hiding this comment.
Avoid process-wide CLI path overrides in parallel tests
When Swift Testing runs this new serialized suite alongside other serialized Gemini suites, this process-wide GEMINI_CLI_PATH mutation can bleed into an in-flight GeminiStatusProbeAPITests or GeminiConsumerTierMigrationTests case that is resolving its own fake CLI. That can make refresh requests use the wrong fixture credentials or fail intermittently even though each suite is internally serialized; prefer injecting the CLI path/task-localizing it or serializing all suites that mutate this variable together.
Useful? React with 👍 / 👎.
Add env overrides, GEMINI_OAUTH2_JS_PATH, and known global install-path discovery so token refresh can proceed without a resolvable gemini binary layout. Surface combined Gemini/Antigravity recovery guidance when OAuth client discovery still fails. Fixes steipete#1978 Co-authored-by: Cursor <cursoragent@cursor.com>
Move OAuth discovery helpers out of the main probe struct and split recovery API tests into their own file to satisfy type_body_length. Co-authored-by: Cursor <cursoragent@cursor.com>
Add Cellar/opt libexec fallback when the gemini binary cannot yield credentials, inject OAuth env via TaskLocal so parallel Gemini suites stay uncontaminated, and document the expanded discovery path. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
4f13206 to
87eaaab
Compare
Summary
Fixes #1978.
When Gemini access tokens expire, CodexBar must read OAuth client credentials from the installed Gemini CLI. If
oauth2.jscannot be found, refresh failed early withCould not find Gemini CLI OAuth configurationbefore Google could return the consumer-tier migration signals handled by #1931.This adds broader OAuth client discovery and clearer recovery guidance.
Changes
GeminiOAuthConfigenv helpers forGEMINI_OAUTH_CLIENT_ID,GEMINI_OAUTH_CLIENT_SECRET, andGEMINI_OAUTH2_JS_PATHoptlibexecpackage roots@TaskLocalso parallel Gemini suites cannot pick leaked process-wide credentialsdocs/gemini.mdTesting
swift test --filter 'GeminiOAuthConfigTests|GeminiOAuthRecoveryAPITests'(5/5 passed)swiftformat+swiftlint --stricton changed filesLive proof (redacted)
Verified on 2026-07-08 against PR head
20e709312with a real~/.gemini/oauth_creds.jsonthat still had a refresh token.Setup shared by both runs
expiry_datein the pastGEMINI_CLI_PATHat a fakegeminibinary that has nooauth2.js/ OAuth client constants.build/debug/CodexBarCLI usage --provider gemini --format json --pretty --statusProof 1 —
GEMINI_OAUTH2_JS_PATHrecoveryRedacted stdout:
[ { "provider" : "gemini", "source" : "oauth-api", "usage" : { "accountEmail" : "<redacted-email>", "identity" : { "accountEmail" : "<redacted-email>", "loginMethod" : "Paid", "providerID" : "gemini" }, "loginMethod" : "Paid", "primary" : { "resetDescription" : "Resets in 23h 59m", "usedPercent" : 0, "windowMinutes" : 1440 }, "updatedAt" : "2026-07-08T14:11:08Z" } } ]Post-run credential check: access token no longer the expired marker;
expiry_dateis in the future;refresh_succeeded=true.Proof 2 — known install-path recovery (no oauth2 path / client env)
Same expired credential + fake CLI, with
GEMINI_OAUTH2_JS_PATH/GEMINI_OAUTH_CLIENT_*unset so discovery must use known Homebrew/npm install paths:Both proofs show the new recovery path can refresh past a missing in-CLI
oauth2.jslayout without the oldCould not find Gemini CLI OAuth configurationdead-end.Related
paidTier.namefor Gemini plan displayed incorrectly #1972)Made with Cursor