PrefectHQ/fastmcp · error · ValueError
Model returned only thinking/reasoning content with no respo
Error message
Model returned only thinking/reasoning content with no response text. / No content in response (finish_reason={candidate.finish_reason}) What it means
On the non-tool sampling path, the response candidate had no usable text content. The error distinguishes two cases: the model emitted only 'thought' (reasoning) parts, or the response contained no content at all (with the finish_reason reported). Raised because a CreateMessageResult requires text content.
Source
Thrown at fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py:341
response: GenerateContentResponse,
model: str,
) -> CreateMessageResult:
"""Convert Google GenAI response to CreateMessageResult (no tools)."""
if not (text := response.text):
candidate = _get_candidate_from_response(response)
# Check if the response only contained thinking
has_thoughts = (
candidate.content
and candidate.content.parts
and all(getattr(p, "thought", False) for p in candidate.content.parts)
)
if has_thoughts:
msg = (
"Model returned only thinking/reasoning content with no response text."
)
else:
msg = f"No content in response (finish_reason={candidate.finish_reason})"
raise ValueError(msg)
return CreateMessageResult(
content=TextContent(type="text", text=text),
role="assistant",
model=model,
)
def _response_to_result_with_tools(
response: GenerateContentResponse,
model: str,
) -> CreateMessageResultWithTools:
"""Convert Google GenAI response to CreateMessageResultWithTools."""
candidate = _get_candidate_from_response(response)
# Determine stop reason and check for function calls
stop_reason: StopReason
finish_reason = candidate.finish_reasonView on GitHub (pinned to 1f02114297)
Solutions
- Disable or reduce thinking/reasoning config (thinking_config with thinking_budget) so the model produces a final text answer.
- Check candidate.finish_reason and adjust the prompt or safety settings accordingly.
- Increase max_tokens if generation was truncated before text was emitted.
- Catch the ValueError and retry or fall back to another sampling handler.
Example fix
// before GenerateContentConfig(thinking_config=ThinkingConfig(thinking_budget=8192)) // after GenerateContentConfig(thinking_config=ThinkingConfig(thinking_budget=0)) # or raise max_tokens
Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try:
result = await client.sample(...)
except ValueError as e:
if 'only thinking' in str(e) or 'No content in response' in str(e):
result = await client.sample(messages=messages, max_tokens=increased, ...) # or disable thinking
else:
raise Prevention
- Allocate enough max_tokens for thinking models to emit a final answer.
- Disable or cap thinking budget when you only need final text.
- Log finish_reason from failures to tune prompts/safety settings.
When it happens
Trigger: Calling Client.sample() through GoogleGenAIHandler.__call__ when the model returns only thinking/reasoning parts (e.g. a thinking model with thinking enabled and no final answer), or the candidate finished without producing text (finish_reason like SAFETY, RECITATION, or empty).
Common situations: Using thinking-capable Gemini models where reasoning output consumed the whole budget; safety filter stopping generation before any text; max tokens consumed by thoughts; malformed prompt producing no output.
Related errors
- No candidate in response from completion.
- No content in response from completion (finish_reason={finis
- No content in response from Anthropic
- Unsupported tool result content type: {type(item).__name__}
- Unsupported content type: {type(content)}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/6d4cdb1ff61a35a5.
Report an issue: GitHub.