fix(google): fail closed on MALFORMED_FUNCTION_CALL without a call part - #943
fix(google): fail closed on MALFORMED_FUNCTION_CALL without a call part#943DevMello wants to merge 1 commit into
Conversation
Gemini usually drops the malformed call upstream, so the final chunk carries only the finishReason and the started-calls guard never fired. The turn surfaced as a clean empty completion instead of an error. MAX_TOKENS with no started call keeps its plain token-limit stop.
📝 WalkthroughWalkthroughGoogle Vertex truncation handling now uses a shared classifier. ChangesGoogle Vertex truncation handling
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Carried onto the review stack as #953 (stack 3/3), unmodified. Your commits were taken with Verified on the stack: This PR stays open until #953 lands. If a maintainer prefers to take yours directly instead, that path is unaffected — the stack commits get dropped and this one merges. Once #953 merges I'll close this as carried, with the credit already in the commit history rather than in a comment. Stack: #951 (plan, base Thanks for the fix. |
|
Leave it as draft. Thanks. It doesnt need any more changes as you can see in juns comment on which you didn't respond to. |
|
Closing this as carried into #953, not as rejected. Your fix is shipping — this is bookkeeping so the same change isn't sitting in the review queue twice. Your commit(s) are on the stack branch as $ git show <yours> | git patch-id --stable
$ git show <carried> | git patch-id --stable
IDENTICALNo content was changed and no conflict resolution was needed. One thing I want to be straight about: my earlier comment said I'd close this after #953 merged, and I'm closing it before. #953 is open and reviewable now, so closing early is my call as maintainer to keep the queue honest — not a signal that the review finished. If the stack doesn't land, reopening this is one click, and the branch is untouched. Verified on the stack: Stack: #951 (plan, base Thanks @DevMello — this was a clean fix and it's in. |
Summary
When Gemini ends a turn with finishReason MALFORMED_FUNCTION_CALL, the malformed call is usually dropped upstream and never arrives as a functionCall part. The fail-closed guard only fired when a call part had been emitted, so the common case surfaced as a clean empty completion and the client treated the turn as answered. The guard now fails closed on MALFORMED_FUNCTION_CALL even with zero started calls, on both the stream and non-stream paths. MAX_TOKENS with no started call keeps its plain token-limit stop, and ai-studio mode is unchanged.
Verification
tests/google-vertex-stream.test.ts: the helper distinction, and the no-call-part malformed case erroring on both the stream and non-stream paths.response.completedwith empty output, nowresponse.failedwith the truncation error. The existing MAX_TOKENS-without-call test stays green.bun run test,typecheck,lint:gui,privacy:scan.Checklist
Summary by CodeRabbit
Bug Fixes
Tests