Skip to content

fix: GoogleGenaiSamplingHandler leaks thought parts and gives unhelpful errors on empty responses#3849

Merged
jlowin merged 5 commits intomainfrom
strawgate/fix-genai-thought-parts-3846
Apr 12, 2026
Merged

fix: GoogleGenaiSamplingHandler leaks thought parts and gives unhelpful errors on empty responses#3849
jlowin merged 5 commits intomainfrom
strawgate/fix-genai-thought-parts-3846

Conversation

@strawgate
Copy link
Copy Markdown
Collaborator

@strawgate strawgate commented Apr 11, 2026

Fixes #3846

Problem

Three related bugs in GoogleGenaiSamplingHandler's response conversion:

  1. Thought parts leak as TextContent — Line 364 has a comment "Skip thought parts" but only checks if part.text: which is truthy for thought parts too. Internal reasoning text appears in MCP responses.

  2. Thinking-only responses crash — When all parts have thought=True, response.text is None (Google SDK filters thoughts), causing ValueError: No content in response: STOP with no indication of why.

  3. Safety errors are unhelpful — Tool-path error says "No content in response from completion" without including finish_reason. A safety-filtered response is indistinguishable from any other empty response.

Fix

  • Filter part.thought == True in _response_to_result_with_tools
  • Include finish_reason in tool-path error message
  • Detect thinking-only responses and provide a specific error message

Tests

7 new unit tests covering thought filtering, safety errors, and normal response passthrough. Tests construct mock GenerateContentResponse objects directly — no API calls.

🤖 Generated with Claude Code

@marvin-context-protocol marvin-context-protocol Bot added bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. client Related to the FastMCP client SDK or client-side functionality. DON'T MERGE PR is not ready for merging. Used by authors to prevent premature merging. labels Apr 11, 2026
@marvin-context-protocol
Copy link
Copy Markdown
Contributor

marvin-context-protocol Bot commented Apr 11, 2026

Test Failure Analysis

(Updated to reflect latest workflow run 24293068620)

Summary: The only failing job is Tests: Python 3.10 on windows-latest. A test in tests/client/test_stdio.py hit the 5-second timeout on the Windows runner — this failure is unrelated to the PR changes.

Root Cause: This is a pre-existing flaky Windows runner issue. The same windows-latest / Python 3.10 job has failed on main in two other recent runs (24285512392 and 24256002384) with the same timeout pattern, each time in a different test file. The PR only modifies google_genai.py, its test file, and a minor fix to test_task_return_types.py — none of which are in test_stdio.py.

Suggested Solution: No action needed on this PR. The failure is a known intermittent Windows CI flake, not introduced by these changes. Re-running the failed job should be sufficient.

Detailed Analysis

Failing job: Tests: Python 3.10 on windows-latest (job 70933497777)

Failure pattern: The test runner reached the 19th test in tests\client\test_stdio.py (18 passed before it), then hit the 5s timeout. A second timeout then occurred while pytest was formatting the error report — specifically inside ntpath.realpath_getfinalpathname on Windows, which is a known Windows path-resolution hang in pytest error formatting.

Relevant log excerpt:

tests\client\test_stdio.py ..................++++++ Timeout ++++++
~~~ Stack of MainThread ~~~
  File "ntpath.py", line 708, in realpath
    if _getfinalpathname(spath) == path:
++++++++++++++++++++++++ Timeout +++++++++++++++++++++
##[error]Process completed with exit code 1.

Evidence this is pre-existing flakiness:

  • Run 24285512392 on main: same Windows job failed, timeout in tests\tools\tool\test_content.py
  • Run 24256002384 on main: same Windows job failed
  • All other jobs (Ubuntu 3.10, Ubuntu 3.13, lowest-direct, MCP conformance, integration) passed

PR changes are unrelated to the failure:

  • src/fastmcp/client/sampling/handlers/google_genai.py
  • tests/client/sampling/handlers/test_google_genai_handler.py
  • tests/server/tasks/test_task_return_types.py
Related Files
  • tests/client/test_stdio.py — the file where the timeout occurred; not modified by this PR
  • src/fastmcp/client/sampling/handlers/google_genai.py — the implementation changed by this PR; unrelated to the failure

Copy link
Copy Markdown

@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: 27c3b2b85a

ℹ️ 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 src/fastmcp/client/sampling/handlers/google_genai.py Outdated
@strawgate strawgate changed the title [DNM] Fix GoogleGenaiSamplingHandler thought part filtering and error messages Fix GoogleGenaiSamplingHandler thought part filtering and error messages Apr 11, 2026
@strawgate strawgate changed the title Fix GoogleGenaiSamplingHandler thought part filtering and error messages fix: GoogleGenaiSamplingHandler leaks thought parts and gives unhelpful errors on empty responses Apr 11, 2026
Copy link
Copy Markdown

@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: 8eb32536a4

ℹ️ 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 src/fastmcp/client/sampling/handlers/google_genai.py
@strawgate strawgate removed the DON'T MERGE PR is not ready for merging. Used by authors to prevent premature merging. label Apr 11, 2026
strawgate and others added 5 commits April 12, 2026 13:10
- Filter thought parts (part.thought=True) from response content instead
  of leaking them as TextContent in _response_to_result_with_tools
- Include finish_reason in error messages when no content is found, so
  safety-filtered responses (SAFETY, RECITATION, etc.) are distinguishable
- Add specific error message for thinking-only responses in
  _response_to_create_message_result

Fixes #3846

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Tests cover:
- Thought parts filtered from tool-path responses
- Thought-only responses produce descriptive errors
- Safety-filtered responses include finish_reason in error
- Normal responses (text + function calls) unaffected

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Remove unused ty: ignore comments from lines where isinstance() narrows
the type, and add correct ty: ignore[invalid-argument-type] and
ty: ignore[not-subscriptable] comments on lines in newly added test
functions where ty cannot infer the union type is a list. Also apply
ruff format fix in test_task_return_types.py.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Addresses review feedback: any() would misclassify mixed responses
(thought + function_call) as thinking-only, hiding the real error.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@jlowin jlowin force-pushed the strawgate/fix-genai-thought-parts-3846 branch from c005b0a to 187823c Compare April 12, 2026 17:10
@jlowin jlowin merged commit d5a3d54 into main Apr 12, 2026
8 checks passed
@jlowin jlowin deleted the strawgate/fix-genai-thought-parts-3846 branch April 12, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. client Related to the FastMCP client SDK or client-side functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] GoogleGenaiSamplingHandler: thought parts leak as TextContent, unhelpful errors on empty/safety responses

2 participants