{"record":{"id":"73b6658a832e9a76","repo":"PrefectHQ/fastmcp","slug":"no-candidate-in-response-from-completion","errorCode":null,"errorMessage":"No candidate in response from completion.","messagePattern":"No candidate in response from completion\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py","lineNumber":319,"sourceCode":"        part = _sampling_content_to_google_genai_part(content)\n\n        if message.role == \"user\":\n            google_messages.append(UserContent(parts=[part]))\n        elif message.role == \"assistant\":\n            google_messages.append(ModelContent(parts=[part]))\n        else:\n            msg = f\"Invalid message role: {message.role}\"\n            raise ValueError(msg)\n\n    return google_messages\n\n\ndef _get_candidate_from_response(response: GenerateContentResponse) -> Candidate:\n    \"\"\"Extract the first candidate from a response.\"\"\"\n    if response.candidates and response.candidates[0]:\n        return response.candidates[0]\n    msg = \"No candidate in response from completion.\"\n    raise ValueError(msg)\n\n\ndef _response_to_create_message_result(\n    response: GenerateContentResponse,\n    model: str,\n) -> CreateMessageResult:\n    \"\"\"Convert Google GenAI response to CreateMessageResult (no tools).\"\"\"\n    if not (text := response.text):\n        candidate = _get_candidate_from_response(response)\n        # Check if the response only contained thinking\n        has_thoughts = (\n            candidate.content\n            and candidate.content.parts\n            and all(getattr(p, \"thought\", False) for p in candidate.content.parts)\n        )\n        if has_thoughts:\n            msg = (\n                \"Model returned only thinking/reasoning content with no response text.\"","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py#L301-L337","documentation":"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.","triggerScenarios":"_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).","commonSituations":"Safety settings filtering the prompt entirely; quota/blocked requests surfacing as empty responses; models returning only promptFeedback with a blockReason; network/proxy truncation.","solutions":["Inspect response.prompt_feedback for a blockReason and adjust the request content or safety settings.","Relax or configure safety settings on the google-genai client (safety_settings) if legitimate content is being blocked.","Retry the request; transient blocks can occur.","Check model name and API key validity — invalid configs can yield empty responses."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try:\n    result = await client.sample(...)\nexcept ValueError as e:\n    if 'No candidate in response' in str(e):\n        # inspect prompt_feedback / adjust safety settings, then retry\n        result = await retry_sample_with_relaxed_safety()\n    else:\n        raise","preventionTips":["Configure safety_settings appropriately for your content domain.","Check prompt content against known safety trigger patterns before sampling.","Retry transient empty responses with backoff."],"tags":["sampling","google-genai","empty-response"],"backgroundTag":"empty-completion-response","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}