Skip to content

fix: disable Gemini thinking to prevent thought_signature replay errors#348

Merged
JeffOtano merged 1 commit intomainfrom
claude/wonderful-tesla-0XicB
May 9, 2026
Merged

fix: disable Gemini thinking to prevent thought_signature replay errors#348
JeffOtano merged 1 commit intomainfrom
claude/wonderful-tesla-0XicB

Conversation

@JeffOtano
Copy link
Copy Markdown
Owner

@JeffOtano JeffOtano commented May 8, 2026

Summary

  • Root cause (Sentry TONALCOACH-1C): Gemini 2.5+ / 3.x models enable "thinking" by default, which attaches a thought_signature to every tool call in the response. @convex-dev/agent does not preserve these provider-specific signatures when it persists messages to the database. On the next conversation turn, when the stored tool calls are replayed to Gemini without their thought_signature, the API rejects the entire request with "Function call is missing a thought_signature in functionCall parts" — surfacing as the generic "I'm having trouble right now" error for users.
  • Fix: Pass providerOptions: { google: { thinkingConfig: { thinkingBudget: 0 } } } to every Gemini streamText call. This disables thinking at the call level, preventing thought_signature from ever being generated and eliminating the replay requirement entirely — for both new and existing conversations.
  • Cleanup: Removed the now-unused re-export shim from resilience.ts (originally for test convenience) and updated resilience.test.ts to import directly from the authoritative source modules (./byokErrors, ./transientErrors).

Changes

File Change
convex/ai/resilience.ts Add providerOptions.google.thinkingConfig.thinkingBudget=0 to thread.streamText() for Gemini; remove stale re-exports
convex/ai/resilience.test.ts Import buildByokErrorMessage, classifyByokError, withByokErrorSanitization, isTransientError directly from source modules
convex/ai/resilienceStreamFailure.test.ts New tests: Gemini calls receive thinkingBudget: 0 providerOptions; Claude/OpenAI/OpenRouter calls do not

Test plan

  • All 1256 backend tests pass (npx vitest run --project backend)
  • New tests in resilienceStreamFailure.test.ts verify the fix is applied for Gemini and not for other providers
  • Prettier formatting passes on all changed files
  • File size hard cap (400 lines) maintained on resilience.ts

https://claude.ai/code/session_015HuaomY3nPah7idvmUGoJz


Generated by Claude Code

Summary by CodeRabbit

  • Updates

    • Modified Gemini provider behavior to disable the thinking feature during streaming operations.
  • Refactor

    • Reorganized internal module structure by consolidating exports to their respective files and removing backward compatibility re-exports.

Review Change Stack

Gemini 2.5+ and 3.x models enable thinking by default, which attaches a
thought_signature to each tool call in the response. @convex-dev/agent
does not preserve these signatures through DB storage, so when the
conversation history is replayed on the next turn Gemini rejects it with
"Function call is missing a thought_signature in functionCall parts".

Fixes this by passing providerOptions.google.thinkingConfig.thinkingBudget=0
to every streamText call for Gemini, which disables thinking entirely and
prevents signatures from being generated in the first place.

Also removes the now-unused re-exports from resilience.ts (they were only
consumed by resilience.test.ts) and updates that test file to import
directly from the source modules.

Fixes TONALCOACH-1C

https://claude.ai/code/session_015HuaomY3nPah7idvmUGoJz
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b7ea3b09-29c8-4025-ab24-dd03efb014bc

📥 Commits

Reviewing files that changed from the base of the PR and between 7c96055 and 84f7b0c.

📒 Files selected for processing (3)
  • convex/ai/resilience.test.ts
  • convex/ai/resilience.ts
  • convex/ai/resilienceStreamFailure.test.ts

📝 Walkthrough

Walkthrough

This PR refactors the resilience module to clean up the public API by removing backward-compatibility re-exports, implements Gemini "thinking" budget control in streaming calls, updates test imports accordingly, and adds comprehensive test coverage validating the Gemini-specific provider options behavior.

Changes

Gemini Thinking Control and Module Cleanup

Layer / File(s) Summary
API Surface Cleanup
convex/ai/resilience.ts
Remove re-exported symbols (buildByokErrorMessage, classifyByokError, withByokErrorSanitization, ByokErrorCode, isTransientError) previously exposed for backward compatibility.
Core Gemini Thinking Control
convex/ai/resilience.ts
Add conditional providerOptions override to streamText call that sets thinkingBudget: 0 for the Gemini provider, disabling its "thinking" feature during streaming attempts.
Test Import Updates
convex/ai/resilience.test.ts
Update imports to source BYOK error helpers from ./byokErrors and transient error helpers from ./transientErrors, removing dependency on resilience module re-exports.
Gemini Thinking Config Test Coverage
convex/ai/resilienceStreamFailure.test.ts
Add ProviderId import and test helpers (makeSuccessAgent, baseStreamWithRetryArgs) to validate streamWithRetry sets providerOptions.google.thinkingConfig.thinkingBudget to 0 for Gemini and does not add Google provider options for other providers.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • JeffOtano/roni#315: Both PRs modify the resilience/transient-error codepath and tests, touching the same functions and Gemini-related behavior around quota handling.
  • JeffOtano/roni#345: Both PRs modify the streaming path in convex/ai/resilience.ts — this PR adds Gemini providerOptions to disable thinking, while the referenced PR adds post-stream error handling.
  • JeffOtano/roni#254: The main PR's removal of re-exports and test import adjustments directly relate to the referenced PR which introduced transient helpers and moved their implementations into convex/ai/transientErrors.ts.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix: disabling Gemini thinking to prevent thought_signature replay errors, which is the primary change in the PR.
Description check ✅ Passed The description follows the template structure with comprehensive Summary, Changes table, and Test Plan sections. All required sections are complete with detailed explanations of the root cause, fix, and validation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/wonderful-tesla-0XicB

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 and usage tips.

@JeffOtano JeffOtano marked this pull request as ready for review May 9, 2026 12:56
@JeffOtano JeffOtano merged commit 522371b into main May 9, 2026
13 checks passed
@JeffOtano JeffOtano deleted the claude/wonderful-tesla-0XicB branch May 9, 2026 15:16
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.

2 participants