Skip to content

fix(sse): treat antigravity empty completions with a normal stop as valid 200s (#14160) - #14243

Open
xiechimon wants to merge 1 commit into
diegosouzapw:release/v3.8.51from
xiechimon:fix/empty-completion-no-model-lockout
Open

xiechimon wants to merge 1 commit into
diegosouzapw:release/v3.8.51from
xiechimon:fix/empty-completion-no-model-lockout

Conversation

@xiechimon

Copy link
Copy Markdown
Contributor

What

An empty (but successful) completion from antigravity's Gemini is treated as a provider failure: the client gets 502 Provider returned empty content and the model is locked out on that account. The reporter sees ~400 of these a day from a single observer prompt the model legitimately answers with no text, which keeps most of a 22-connection pool excluded and starves unrelated clients (their words: a cheap harmless request was starving the expensive ones).

The fake-success guard exists for free-tier/scraping providers whose failure mode is an empty 200 shell (#13461). Antigravity is Google's first-party Gemini API: an empty candidate with finishReason: STOP is a real result, and retrying the same prompt on the next account returns the same empty answer anyway.

Changes

  • isEmptyContentResponse() gains an optional provider and a TRUSTED_EMPTY_STOP_PROVIDERS allowlist (same pattern as the provider-allowlisted classifyFakeSuccessBody from [BUG] Gateway returning bad response #13461). On antigravity, an empty completion with a normal terminal stop reason (openai stop, claude end_turn) is no longer flagged.
  • The non-streaming leg passes its provider through, so these completions flow to the client as a valid 200 with empty content instead of a synthetic 502. No failure accounting, no model lockout, and no retrying the same prompt on the next account to get the same empty answer.

Unchanged: every other provider keeps the guard, including on empty stop completions; antigravity responses with no terminal stop reason are still flagged; the existing legit-empty carve-outs (length, tool_calls, content_filter, max_tokens, tool_use) are untouched.

Verification

  • New test tests/unit/14160-antigravity-empty-stop-completion.test.ts, 5 cases: antigravity empty+stop and empty+end_turn pass through; untrusted providers and the no-provider call keep flagging them; an antigravity empty shell with no finish reason is still flagged; existing carve-outs unchanged.
  • Red-green checked against base: with the src changes reverted and only the test kept, the 2 antigravity cases fail and the 3 controls pass; with the fix, 5/5 pass.
  • Adjacent suites: 199/199 across the error-classifier, non-streaming-leg, empty-content, fake-success, and silent-empty web-provider suites (incl. combo-empty-content-failover-5085, diagnostics-fake-success-13461, copilot-m365-web-silent-empty-7858, zai-web-silent-empty-repro).
  • prettier --check, eslint, typecheck:core clean on all touched files.

Out of scope: the streaming variant (#13600) is a different code path (streamEmptyChoices.ts) and is not touched here. If you'd rather have the passthrough behind a settings toggle, happy to add one.

Fixes #14160

…alid 200s (diegosouzapw#14160)

An empty completion from antigravity's Gemini can be a real answer:
some prompts legitimately produce no text, and the upstream reports a
normal terminal finish reason (STOP -> "stop"). The fake-success guard
in isEmptyContentResponse flagged these regardless, so the
non-streaming leg rewrote them into synthetic 502s that fed model
lockout — a few hundred such "failures" a day kept most of the
reporter's 22-connection pool excluded and starved unrelated clients.

The guard exists for free-tier/scraping providers whose failure mode is
an empty 200 shell (diegosouzapw#13461), so scope the exemption the same way the
repo scopes classifyFakeSuccessBody: a trusted-provider allowlist. On
antigravity, an empty completion with a normal stop reason (openai
"stop", claude "end_turn") now passes through as a valid 200; every
other provider keeps the existing guard, and antigravity responses with
no terminal stop reason are still flagged.
Copilot AI lite review requested due to automatic review settings September 20, 2026 05:22

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

This was referenced Sep 20, 2026
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] empty gemini completion is treated as provider failure: 502 + model lockout drains the antigravity pool

2 participants