Skip to content

fix(google): let the empty-completion retry replay a pre-output Vertex malformed call - #6881

Merged
lidge-jun merged 2 commits into
devfrom
codex/6876-vertex-malformed-call-replay
Oct 10, 2026
Merged

lidge-jun merged 2 commits into
devfrom
codex/6876-vertex-malformed-call-replay

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

Through Claude Code, gemini-3.8-flash on Vertex AI keeps failing turns with 502 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_CALL terminal with zero started tool calls with a proxy-internal replaySafeBeforeOutput flag, and the empty-completion guard treats such an error like an empty completion: when emptyCompletionRetry is enabled it replays the identical request once. Claude Messages requests reach the same guard through the internal Responses replay.

Unchanged on purpose:

  • The default stays off. Without emptyCompletionRetry: true the client sees the same error as before.
  • A truncation after a started tool call, or any error after text or a tool call reached the client, is never replayed.
  • If the retry fails the same way, the client gets the specific Vertex message (with usage from both attempts) instead of the generic empty_completion_retry_failed text.
  • The flag is never serialized: the bridges pick error fields explicitly.
  • Vertex truncation errors now carry the usage Vertex reported, so a replayed turn meters both billable attempts.

The emptyCompletionRetry row 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-call MALFORMED_FUNCTION_CALL (stream and non-stream) and never tags a truncation after a started call.
  • Negative control: with the src/ change stashed, four of the new assertions fail.
  • bun test tests/adapters/google: 689 pass, 1 fail in google-models-listing.test.ts when 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.
  • Full suite not run locally; coverage left to hosted CI. No live Vertex request was made, so whether one replay clears the reporter's repeated failure is not verified.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • Bug Fixes
    • Added a single retry for certain Vertex AI malformed function-call failures that occur before any response or tool-call output. Failures after output begins are not retried.
    • Preserved the original error when the retry encounters the same failure, and clarified when retries apply.
    • Usage from both attempts is included when a retry occurs.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner October 10, 2026 09:09
@lidge-jun lidge-jun added the bug Something isn't working label Oct 10, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-10T09:13:30.718105Z 939e86a PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 7a744c7b-467b-4885-852f-25a83484e532


📥 Commits

Reviewing files that changed from the base of the PR and between 939e86a and e955b94.



📒 Files selected for processing (3)
  • src/adapters/google-truncation.ts
  • src/adapters/google.ts
  • tests/adapters/google/google-vertex-stream.test.ts


Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.




📝 Walkthrough
📝 Walkthrough

Walkthrough

Vertex and Cloud Code Assist truncation errors now carry a replay-safety flag only for pre-output MALFORMED_FUNCTION_CALL failures with no started tool calls. When retries are enabled and within the retry limit, the empty-completion guard retries the identical turn and merges usage.

Changes

Vertex truncation retry

Layer / File(s) Summary
Classify Vertex truncation events
src/types/request.ts, src/adapters/google-truncation.ts, src/adapters/google.ts, tests/adapters/google/google-vertex-stream.test.ts
The adapter marks MALFORMED_FUNCTION_CALL truncations replay-safe only when no tool calls started. Streaming and buffered parsing use the shared error-event helper. Tests check eligible and ineligible truncations and usage.
Retry replay-safe pre-output errors
src/server/responses/empty-completion-guard.ts, tests/responses/empty-completion-hardening.test.ts, docs-site/src/content/docs/reference/configuration/server.md
The guard merges usage and retries replay-safe errors within its retry limit. Tests cover successful and repeated retries, errors after output, and ordinary upstream errors. The configuration documentation lists eligible Vertex failures.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant VertexAI as Vertex AI
  participant GoogleAdapter as Google adapter
  participant EmptyCompletionGuard as empty-completion guard
  participant Continuation as continuation
  VertexAI->>GoogleAdapter: MALFORMED_FUNCTION_CALL truncation
  GoogleAdapter->>EmptyCompletionGuard: replay-safe error when no tool calls started
  EmptyCompletionGuard->>Continuation: retry identical turn
  Continuation-->>EmptyCompletionGuard: answer or retry error
Loading


Merge Risk: ⚪ Minimal · up to e955b

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 | Passed 3 | Failed 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check Warning Issue #6876 is an active directly linked bug. It expects the affected Claude Code flow to complete its file reads and tool calls and return the GSD progress output instead of repeatedly returning the … Make the qualifying pre-output Vertex failure handle the reported configuration, or provide an explicit configuration change for the affected Claude Code path that enables emptyCompletionRetry. Add an automated assertion for that effectiv…
Docstring Coverage Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 6 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Out of Scope Changes check Passed The production changes remain connected to issue #6876. src/adapters/google-truncation.ts classifies the Vertex terminal, src/adapters/google.ts supplies usage and the shared event, `src/server/re…
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: allowing empty-completion retry for a pre-output Vertex MALFORMED_FUNCTION_CALL.

Full details: Linked Issues check

Explanation

Issue #6876 is an active directly linked bug. It expects the affected Claude Code flow to complete its file reads and tool calls and return the GSD progress output instead of repeatedly returning the Vertex 502 MALFORMED_FUNCTION_CALL. src/adapters/google-truncation.ts and src/server/responses/empty-completion-guard.ts implement and test a qualifying replay, including usage merging and protection after output. However, the guard remains opt-in through emptyCompletionRetry. The issue provides no enabled configuration, and its redacted configuration is empty. With the reported default configuration, replaySafeBeforeOutput is not replayed and the same 502 remains. The PR also reports no live Vertex validation, so resolution of the observed flow is not established.

Resolution

Make the qualifying pre-output Vertex failure handle the reported configuration, or provide an explicit configuration change for the affected Claude Code path that enables emptyCompletionRetry. Add an automated assertion for that effective configuration. Validate that the affected path completes the required reads and tool calls and returns the GSD progress output.


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR





🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR



  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/adapters/google.ts Outdated
if ((provider.googleMode === "vertex" || provider.googleMode === "cloud-code-assist")
&& isVertexTruncatedTurn(lastFinishReason, toolCallsStarted)) {
yield { type: "error", message: vertexTruncationErrorMessage(lastFinishReason) };
yield vertexTruncationErrorEvent(lastFinishReason, toolCallsStarted);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment on lines +296 to +300
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@lidge-jun
lidge-jun merged commit 7751208 into dev Oct 10, 2026
34 of 39 checks passed
@lidge-jun
lidge-jun deleted the codex/6876-vertex-malformed-call-replay branch October 10, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant