Repository navigation
fix(antigravity): surface Google 429 quota exhaustion instead of retrying it - #427
Merged
Merged
Conversation
pc_b35cf668bc26 Parse the full Cloud Code body so a 500-character prefix cannot drop the Google status and message. An exhausted 5h bucket from retrieveUserQuotaSummary is non-retryable quota.
…gravity-quota-errors-c5e1
shuv1337
marked this pull request as ready for review
October 5, 2026 03:11
This was referenced Oct 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
The captain approved resuming the issue backlog (2026-10-04): "triage the ~22 Cursor draft PRs first, then small batches", and later answered yes that shuvbro triage review counts as the first review for these Cursor PRs. The read-only triage report at ~/repos/shuvbro/data/triage-cursor-shuvcode/report.md identifies #427 (fix(antigravity): surface Google 429 quota instead of retrying it, issue #404) as fix-then-land. P1: packages/antigravity-plugin/src/wire.ts:390-393 on the PR head lets fiveHourWindow fall back to ANY group 5h bucket when the failed model group is missing, so a Gemini RESOURCE_EXHAUSTED/RATE_LIMIT_EXCEEDED with only an exhausted Claude/GPT summary is classified QuotaExceeded, retryable=false - a transient throttle becomes terminal (reproduced with the real parser). Required: use only the quota group demonstrably belonging to the failed model; a missing/unrecognized group must not borrow another group exhaustion; keep explicit QUOTA_EXHAUSTED and affirmative long-window handling; add cross-group and missing-group regressions plus a response-hook integration regression proving the full body and classification reach the session. The referenced triage section says the full-body parsing and synthetic Google ErrorInfo are otherwise aligned with the quota-plugin group format; current default does not explain non-ok responses or classify quota_exhausted, so the issue fix remains needed after correcting model-group attribution.
What Changed
The Antigravity plugin's
http.responsehook now handles failed responses to rewritten Cloud Code requests. It parses the full error body, including nested Google errors and SSEdata:payloads. On a 429 it also requests a best-effort quota readout from theretrieveUserQuotaSummaryendpoint, which is new inoauth.ts. It then sends back a Google-format error with the Cloud Code status, the message, a summary of each quota window and a syntheticErrorInforeason.A
RESOURCE_EXHAUSTEDerror becomes non-retryableQUOTA_EXHAUSTEDonly in these cases:QUOTA_EXHAUSTEDreason.All other
RESOURCE_EXHAUSTEDerrors remain retryable throttles.@opencode/aiprovider-error classification now treats thequota_exhaustedreason as a quota code.Added tests in
packages/antigravity-plugin/test/error.test.ts,packages/ai/test/provider-error.test.tsand the newpackages/core/test/session-antigravity-error.test.ts:The plugin README also documents this behavior.
Risk Assessment
✅ Low: The 5h-window lookup now returns only the bucket for the failed model's group ("gemini:5h" or "3p:5h") and never falls back to another group. Explicit QUOTA_EXHAUSTED and long-window message handling are kept. Cross-group, missing-group, unknown-model, and response-hook regressions cover the required behavior, and the group naming matches packages/quota-plugin/src/google.ts.
Testing
After installing dependencies, I ran the targeted antigravity wire tests, the core session response-hook integration test and the ai classifier test; all pass. An A/B run against the pre-fix wire.ts shows the 6 new cross-group and missing-group regressions failing before the fix, which confirms they reproduce the P1. A temporary scratch test also drove the real plugin response hook with the quota-summary fetch path turned on. For a Gemini throttle, an exhausted Claude/GPT or unknown group stays RATE_LIMIT_EXCEEDED, and only an exhausted Gemini group becomes QUOTA_EXHAUSTED. These are unit and in-process integration results, not live results. Nothing ran against a real live Google 429, because that needs a real Antigravity OAuth account in a throttled or exhausted state against the hardcoded cloudcode-pa endpoint. There is no UI surface, so no screenshots were taken. The worktree is clean.
Evidence: Wire fix diff (fiveHourWindow no longer falls back to any group)
Evidence: A/B: pre-fix wire.ts fails the 6 cross/missing-group regressions
Evidence: Response hook with quota summary: rewritten bodies per summary group for a Gemini throttle
Claude + GPT exhausted -> reason RATE_LIMIT_EXCEEDED (retryable) Gemini models exhausted -> reason QUOTA_EXHAUSTED Unknown models exhausted -> reason RATE_LIMIT_EXCEEDED (retryable)Evidence: Session integration test output
Evidence: Antigravity wire test output
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
⏭️ **Rebase** - skipped
Step was skipped.
✅ **Review** - passed
✅ No issues found.
bun install(worktree had no node_modules)cd packages/antigravity-plugin && bun test test/error.test.ts(16 pass)cd packages/core && bun test test/session-antigravity-error.test.ts(3 pass: QUOTA_EXHAUSTED→QuotaExceeded non-retryable, 5h-reset message→QuotaExceeded, plain throttle→RateLimit retryable, full >500-char body reaches the session)cd packages/ai && bun test test/provider-error.test.ts -t "Google 5h"(1 pass)A/B:git show 0d0fc791b4:packages/antigravity-plugin/src/wire.tsswapped in, then error.test.ts reran (6 cross-/missing-group regressions fail before the fix), then restored withgit checkout HEAD -- wire.tsTemporary scratch variant of the session integration test (deleted afterwards): drives the real GoogleAntigravityPlugin http.response hook with the quota-summary fetch enabled and a stubbed retrieveUserQuotaSummary returning an exhausted Claude+GPT / Gemini / Unknown group for a Gemini model✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.