Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(coderd/x): surface Gemini malformed-function-call stream deaths as retryable errors - #28470

Merged
ibetitsmike merged 4 commits into
mainfrom
mike/gemini-malformed-call-silent-death
Aug 24, 2026
Merged

fix(coderd/x): surface Gemini malformed-function-call stream deaths as retryable errors#28470
ibetitsmike merged 4 commits into
mainfrom
mike/gemini-malformed-call-silent-death

Conversation

@ibetitsmike

Copy link
Copy Markdown
Collaborator

Problem

When Gemini's OpenAI-compatible endpoint rejects a model-generated function call server-side, it ends the SSE stream cleanly with the nonstandard finish reason function_call_filter: MALFORMED_FUNCTION_CALL after streaming only thought summaries; the rejected call never reaches the wire. chatd treated this as a normal completion: fantasy maps the unrecognized finish reason to unknown, the reasoning block never closes (the only non-thought delta is the </thought> marker, which the transport seam strips to an empty string, and the openaicompat hook only ends reasoning on a non-empty content delta), so the step accumulates no content and the generation loop finishes the turn as complete. The user sees the model think for ~40 seconds and then nothing: no assistant message, no last_error, chat status waiting. Observed twice in a row in production on gemini-3.7-flash, with "Resume" reproducing it identically.

Fix

Two independent layers:

  • coderd/x/googleopenai: the stream rewrite now converts any chunk whose finish_reason starts with function_call_filter into an OpenAI-style SSE {"error": ...} event embedding the raw reason. openai-go turns error-bearing events into stream errors, so the failure rides the existing stream-error path instead of ending the stream cleanly.
  • coderd/x/chatd/chaterror: classifies that injected error as retryable (kind generic, provider google) with a clear user-facing message, so the existing generation retry machinery re-runs the step and persists a last_error if retries exhaust.
  • coderd/x/chatd/chatloop: provider-agnostic guard: a step that produced no user-visible content and no tool calls under a finish reason of unknown, error, other, or tool-calls (a tool-calls finish that delivered zero calls) now returns a retryable error instead of silently completing the turn. stop and length finishes keep their existing semantics.

Tests cover the seam rewrite (live-capture SSE shape plus standard finish reason passthrough), the new classification, and the chatloop guard (error cases plus preserved stop, length, text, and tool-call behavior). Each layer was red-green verified independently.

Remote dogfood UAT ran against this exact commit: normal reasoning and tool-call chats on a real model complete cleanly with no spurious guard errors and no retry loops. The Google-side failure itself is not deterministically triggerable against live Gemini and is owned by the unit tests.

Xum acted on Mike's (@ibetitsmike) behalf.

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: 28b3ab53a7

ℹ️ 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 coderd/x/chatd/chaterror/classify.go Outdated
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: c591b3f7a0

ℹ️ 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 coderd/x/chatd/chatloop/chatloop.go
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 30b2bb06df

ℹ️ 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".

@ibetitsmike
ibetitsmike force-pushed the mike/gemini-malformed-call-silent-death branch from 30b2bb0 to fb8e805 Compare August 24, 2026 13:36
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: fb8e805aac

ℹ️ 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 coderd/x/chatd/chatloop/chatloop.go
@ibetitsmike
ibetitsmike marked this pull request as ready for review August 24, 2026 15:08
@ibetitsmike
ibetitsmike merged commit a48aedd into main Aug 24, 2026
32 of 33 checks passed
@ibetitsmike
ibetitsmike deleted the mike/gemini-malformed-call-silent-death branch August 24, 2026 15:09
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants