Skip to content

fix: handle Gemini 3 Pro reasoning-only and blocked empty responses#11497

Draft
roomote[bot] wants to merge 1 commit intomainfrom
fix/gemini-3-pro-reasoning-only-empty-response
Draft

fix: handle Gemini 3 Pro reasoning-only and blocked empty responses#11497
roomote[bot] wants to merge 1 commit intomainfrom
fix/gemini-3-pro-reasoning-only-empty-response

Conversation

@roomote
Copy link
Contributor

@roomote roomote bot commented Feb 17, 2026

Related GitHub Issue

Closes: #11492

Description

This PR attempts to address Issue #11492 where Gemini 3 Pro Preview causes provider errors roughly every 2-3 requests. Feedback and guidance are welcome.

Root cause: gemini-3-pro-preview sometimes returns reasoning/thinking content but no actionable text or tool calls. The existing empty-response detection in Task.ts only checks for text and tool_use content, treating reasoning-only responses as failures. Additionally, non-STOP finish reasons (SAFETY, RECITATION) from Gemini are silently swallowed, giving users no diagnostic information.

Changes made:

  1. src/api/providers/gemini.ts: Surface non-STOP finishReason as descriptive errors when no content is produced. This gives Task.ts retry logic (and users) a meaningful error message instead of the generic "no assistant messages" error.

  2. src/core/task/Task.ts: Handle reasoning-only responses (thinking content present but no text/tool calls) as transient issues:

    • Do not increment consecutiveNoAssistantMessagesCount (free retry without triggering error UI)
    • Auto-retry reasoning-only responses even without autoApprovalEnabled, since the model clearly attempted to respond
  3. src/api/providers/__tests__/gemini-handler.spec.ts: Added 5 test cases covering:

    • Non-STOP finish reason with no content (throws descriptive error)
    • STOP finish reason with no content (does not throw)
    • Reasoning-only responses (yields reasoning chunks, no text)
    • RECITATION finish reason (throws descriptive error)
    • Non-STOP finish reason with content present (does not throw)

Test Procedure

  1. Run cd src && npx vitest run api/providers/__tests__/gemini-handler.spec.ts -- all 15 tests pass
  2. Run cd src && npx vitest run api/providers/__tests__/gemini.spec.ts -- all 17 existing tests still pass
  3. Lint and type checks pass via pre-push hooks

Pre-Submission Checklist

  • Issue Linked: This PR is linked to an approved GitHub Issue (see "Related GitHub Issue" above).
  • Scope: My changes are focused on the linked issue (one major feature/fix per PR).
  • Self-Review: I have performed a thorough self-review of my code.
  • Testing: New and/or updated tests have been added to cover my changes.
  • Documentation Impact: No documentation updates required (internal behavior change).
  • Contribution Guidelines: I have read and agree to the Contributor Guidelines.

Documentation Updates

No documentation updates needed. This is an internal behavior fix for Gemini provider error handling.

Start a new Roo Code Cloud session on this branch

- Surface non-STOP finishReason (SAFETY, RECITATION, etc.) as descriptive
  errors instead of generic "no assistant messages" when Gemini returns
  no content
- Treat reasoning-only responses (thinking content but no text/tool calls)
  as transient issues with free retry (no consecutive failure increment)
- Auto-retry reasoning-only responses even without autoApproval enabled
- Add tests for empty response, reasoning-only, and blocked response
  scenarios

Closes #11492
@roomote
Copy link
Contributor Author

roomote bot commented Feb 17, 2026

Rooviewer Clock   See task

Reviewed the Gemini handler and Task.ts changes. One issue flagged:

  • Reasoning-only responses retry indefinitely without an upper bound or user prompt (Task.ts lines 3642-3675). Consider capping retries or falling through to the user consent flow after a fixed number of attempts.

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Comment on lines 3642 to 3675
@@ -3657,12 +3668,18 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {

// Check if we should auto-retry or prompt the user
// Reuse the state variable from above
if (state?.autoApprovalEnabled) {
// For reasoning-only responses, always auto-retry silently since the
// model clearly attempted to respond (produced thinking content) but
// just didn't generate actionable output. This avoids bothering the
// user with retry prompts for transient Gemini 3 Pro behavior.
if (state?.autoApprovalEnabled || hasReasoningOnly) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

When hasReasoningOnly is true, consecutiveNoAssistantMessagesCount is never incremented (line 3646) and the auto-retry fires unconditionally (line 3675, || hasReasoningOnly). This means reasoning-only responses bypass both the failure counter and the user-consent prompt, retrying indefinitely with no upper bound. If the model persistently returns reasoning-only responses (the issue reports ~33% failure rate), several consecutive reasoning-only responses would silently consume API credits and spin with exponential backoff but no termination condition. Consider either (a) capping reasoning-only retries to a small fixed count (e.g. 3) before falling through to the user prompt, or (b) still incrementing consecutiveNoAssistantMessagesCount but raising the threshold before showing the error UI.

Fix it with Roo Code or mention @roomote and request a fix.

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.

[BUG] Gemini 3 pro causes provider errors

1 participant

Comments