Skip to content

fix: resolve Google Gemini 3 'Invalid Input' error on tool calls#35

Merged
sichengchen merged 3 commits intomainfrom
fix/google-provider-invalid-input
Mar 1, 2026
Merged

fix: resolve Google Gemini 3 'Invalid Input' error on tool calls#35
sichengchen merged 3 commits intomainfrom
fix/google-provider-invalid-input

Conversation

@sichengchen
Copy link
Owner

Summary

  • Enable explicit thinking: { enabled: true } for Gemini 3 models in getStreamOptions() so thought signatures are reliably generated on function calls — fixes the 400 Invalid Input / thought_signature error
  • Add retry logic (max 2 retries, exponential backoff) in the agent stream loop for transient provider errors (429, 500, 503, rate limit, thought_signature)
  • Sanitize message history on retry to remove error messages that would corrupt the conversation

Test plan

  • bun run typecheck — clean (only pre-existing @chat-adapter/telegram module error)
  • bun run lint — clean
  • bun test — 709 pass, 9 skip, 1 fail + 1 error (both pre-existing)
  • Manual: verified thinking config is generated for gemini-3-flash-preview
  • Manual: verified retry logic fires on 429 rate limit

🤖 Generated with Claude Code

sichengchen and others added 3 commits March 1, 2026 00:14
Gemini 3 models require thoughtSignature on all functionCall parts in
conversation history. Without explicit thinking config, signatures may
be missing, causing 400 "Invalid Input" on replay.

- Enable thinking for Gemini 3 in ModelRouter.getStreamOptions()
- Add retry logic (max 2) with exponential backoff for transient errors
  (429, 500, 503, thought_signature)
- Log error metadata (model, messages, tools) on stream failures
- Sanitize message history before retry to remove corrupted entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sichengchen sichengchen merged commit a71ba13 into main Mar 1, 2026
2 checks passed
Copy link

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

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: 1d2acc96f3

ℹ️ 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 (attempt <= MAX_STREAM_RETRIES && isRetryableError(errorMsg) && !ac?.signal.aborted) {
// Don't push the error message into history — it would corrupt the conversation
// Sanitize history in case the error was caused by malformed messages
this.messages = sanitizeHistoryForRetry(this.messages);

Choose a reason for hiding this comment

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

P1 Badge Rebuild stream context after sanitizing retry history

When a retryable provider error occurs, sanitizeHistoryForRetry assigns a new array to this.messages, but the retry loop keeps reusing the context object that was created before the loop. Because context.messages still points to the old array, retries resend the unsanitized history, so failures like Gemini thought_signature errors can repeat on every attempt instead of recovering. This affects any path that relies on history sanitization before retry.

Useful? React with 👍 / 👎.

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.

1 participant