Repository navigation
fix(google): let the empty-completion retry replay a pre-output Vertex malformed call - #6881
Conversation
…x malformed call (#6876)
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to Retries are limited to eligible pre-output malformed-call failures and preserve usage if the retry fails. No merge-blocking regression is established; the reported live Vertex incident has not been validated. Pre-merge checks |
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 939e86ad2f
ℹ️ 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".
| if ((provider.googleMode === "vertex" || provider.googleMode === "cloud-code-assist") | ||
| && isVertexTruncatedTurn(lastFinishReason, toolCallsStarted)) { | ||
| yield { type: "error", message: vertexTruncationErrorMessage(lastFinishReason) }; | ||
| yield vertexTruncationErrorEvent(lastFinishReason, toolCallsStarted); |
There was a problem hiding this comment.
Carry Vertex usage into replay-safe terminal events
When Vertex includes usageMetadata with a pre-output MALFORMED_FUNCTION_CALL, the streaming parser has already stored it in pendingUsage, but this new event omits it; the buffered path similarly returns before converting json.usageMetadata. Consequently, the guard's mergeUsage(usage, event.usage) receives no first-attempt usage, so a successful retry underreports billed tokens in the client response and request accounting. Pass the captured usage into vertexTruncationErrorEvent in both parser paths and cover this with an adapter-to-guard regression test.
AGENTS.md reference: src/AGENTS.md:L19-L19
Useful? React with 👍 / 👎.
| if (event.replaySafeBeforeOutput === true && retries < maxRetries) { | ||
| // The upstream failed the turn before any text or tool call (#6876: Vertex dropped a | ||
| // malformed function call). Nothing actionable reached the client, so this is the same | ||
| // replay-safe shape as an empty completion: retry the identical turn once. | ||
| usage = mergeUsage(usage, event.usage); |
There was a problem hiding this comment.
Update the owned structure docs for the retry contract
This adds a shared adapter event flag and changes the Responses retry policy, but the commit updates no file under structure/. The repository requires every structure document mapped to changed shared adapter, transport, server, and type areas in structure/INDEX.md to be updated in the same change; document the new replay-safe terminal and usage/retry semantics in those owners rather than only in the public configuration table.
AGENTS.md reference: src/AGENTS.md:L11-L11
Useful? React with 👍 / 👎.
|
✅ Deterministic PR hygiene checks passed. |
Summary
Through Claude Code,
gemini-3.8-flashon Vertex AI keeps failing turns with502 Vertex AI response truncated upstream before the turn completed (MALFORMED_FUNCTION_CALL)(#6876). Vertex reports this finish reason when the model produced a function call it could not parse; the call is dropped and the turn carries no text and no tool call. OpenCodex correctly fails closed here (#953), but the error terminal also took these turns out of reach of the opt-in empty-completion retry, which exists for exactly this shape: a turn that ended before anything actionable reached the client.This marks that one case as replay-safe. The Vertex adapter now tags a
MALFORMED_FUNCTION_CALLterminal with zero started tool calls with a proxy-internalreplaySafeBeforeOutputflag, and the empty-completion guard treats such an error like an empty completion: whenemptyCompletionRetryis enabled it replays the identical request once. Claude Messages requests reach the same guard through the internal Responses replay.Unchanged on purpose:
emptyCompletionRetry: truethe client sees the same error as before.empty_completion_retry_failedtext.The
emptyCompletionRetryrow in the server configuration reference now mentions this case.Closes #6876
Verification
bun test tests/responses/empty-completion-hardening.test.ts tests/adapters/google/google-vertex-stream.test.ts tests/responses/empty-completion-guard.test.ts tests/adapters/bridge-nonstreaming-terminal.test.ts: 102 pass. An end-to-end case feeds real Vertex adapter events through the guard and checks that the retried turn reports usage from both attempts. New cases: replay-safe error before output retries once and merges usage; a repeat surfaces the Vertex message; a replay-safe error after output passes through; an ordinary pre-output error is still not retried; the adapter tags zero-callMALFORMED_FUNCTION_CALL(stream and non-stream) and never tags a truncation after a started call.src/change stashed, four of the new assertions fail.bun test tests/adapters/google: 689 pass, 1 fail ingoogle-models-listing.test.tswhen run as a directory; that file passes 14/14 alone both with and without this change, so it is cross-file state in the directory run, not this PR.bun x tsc --noEmit: exit 0.Checklist
Summary by CodeRabbit