PrefectHQ/fastmcp · error · ValueError

No candidate in response from completion.

Error message

No candidate in response from completion.

What it means

After a completion call, the handler expects the Gemini response to contain at least one candidate. If response.candidates is empty or the first candidate is falsy, ValueError is raised. Candidates can be absent when the request is blocked (safety filters, invalid request) before any generation happens.

Source

Thrown at fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py:319

        part = _sampling_content_to_google_genai_part(content)

        if message.role == "user":
            google_messages.append(UserContent(parts=[part]))
        elif message.role == "assistant":
            google_messages.append(ModelContent(parts=[part]))
        else:
            msg = f"Invalid message role: {message.role}"
            raise ValueError(msg)

    return google_messages


def _get_candidate_from_response(response: GenerateContentResponse) -> Candidate:
    """Extract the first candidate from a response."""
    if response.candidates and response.candidates[0]:
        return response.candidates[0]
    msg = "No candidate in response from completion."
    raise ValueError(msg)


def _response_to_create_message_result(
    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."

View on GitHub (pinned to 1f02114297)

Solutions

  1. Inspect response.prompt_feedback for a blockReason and adjust the request content or safety settings.
  2. Relax or configure safety settings on the google-genai client (safety_settings) if legitimate content is being blocked.
  3. Retry the request; transient blocks can occur.
  4. Check model name and API key validity — invalid configs can yield empty responses.
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try:
    result = await client.sample(...)
except ValueError as e:
    if 'No candidate in response' in str(e):
        # inspect prompt_feedback / adjust safety settings, then retry
        result = await retry_sample_with_relaxed_safety()
    else:
        raise

Prevention

When it happens

Trigger: _get_candidate_from_response is invoked from _response_to_create_message_result or _response_to_result_with_tools when the GenerateContentResponse from the Gemini API has no candidates (e.g. response was blocked by safety filters or prompt blocked).

Common situations: Safety settings filtering the prompt entirely; quota/blocked requests surfacing as empty responses; models returning only promptFeedback with a blockReason; network/proxy truncation.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/73b6658a832e9a76. Report an issue: GitHub.