{"record":{"id":"75b43afd7bfc0309","repo":"PrefectHQ/fastmcp","slug":"no-content-in-response-from-completion","errorCode":null,"errorMessage":"No content in response from completion","messagePattern":"No content in response from completion","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/sampling/handlers/openai.py","lineNumber":403,"sourceCode":"        return openai_messages\n\n    @staticmethod\n    def _chat_completion_to_create_message_result(\n        chat_completion: ChatCompletion,\n    ) -> CreateMessageResult:\n        if len(chat_completion.choices) == 0:\n            raise ValueError(\"No response for completion\")\n\n        first_choice = chat_completion.choices[0]\n\n        if content := first_choice.message.content:\n            return CreateMessageResult(\n                content=TextContent(type=\"text\", text=content),\n                role=\"assistant\",\n                model=chat_completion.model,\n            )\n\n        raise ValueError(\"No content in response from completion\")\n\n    def _select_model_from_preferences(\n        self, model_preferences: ModelPreferences | str | list[str] | None\n    ) -> ChatModel:\n        for model_option in self._iter_models_from_preferences(model_preferences):\n            if model_option in get_args(ChatModel):\n                chosen_model: ChatModel = model_option  # type: ignore[assignment]  # ty:ignore[invalid-assignment]\n                return chosen_model\n\n        return self.default_model\n\n    @staticmethod\n    def _convert_tools_to_openai(tools: list[Tool]) -> list[ChatCompletionToolParam]:\n        \"\"\"Convert MCP tools to OpenAI tool format.\"\"\"\n        openai_tools: list[ChatCompletionToolParam] = []\n        for tool in tools:\n            # Build parameters dict, ensuring required fields\n            parameters: dict[str, Any] = dict(tool.input_schema)","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py#L385-L421","documentation":"The completion had at least one choice, but the first choice's message has no text content (empty string or None). Since the plain sampling result path only supports text output, the handler raises this ValueError instead of returning an empty CreateMessageResult.","triggerScenarios":"A ChatCompletion whose first choice's message.content is '' or None reaches _chat_completion_to_create_message_result — e.g. the model finished without emitting text (abnormal stop, length exhaustion before any tokens, or refusal producing empty content).","commonSituations":"max_tokens set so low the model emits nothing; content filter stripping the message body; model returning only tool calls while using the plain (no-tools) sampling path; deprecated or broken model returning empty bodies.","solutions":["Increase max_tokens in the sampling params so the model can emit text.","Check finish_reason on the choice — 'content_filter' or 'length' indicates truncation/blocking, not a model bug.","If tool calls are expected, use the tools-capable result path instead of the plain one.","Catch the ValueError and retry with adjusted parameters or fall back to another provider."],"exampleFix":"// before\nparams = CreateMessageRequestParams(messages=messages, maxTokens=1)\n// after\nparams = CreateMessageRequestParams(messages=messages, maxTokens=1024)","handlingStrategy":"validation","validationCode":"def assert_completion_has_text(completion):\n    if not completion.choices:\n        raise ValueError('No choices')\n    if not completion.choices[0].message.content:\n        raise ValueError('First choice has no text; check finish_reason/max_tokens')","typeGuard":"def has_text_content(completion) -> bool:\n    return bool(completion.choices and completion.choices[0].message.content)","tryCatchPattern":"try:\n    result = await sampling_handler(messages, params)\nexcept ValueError as e:\n    if str(e) == 'No content in response from completion':\n        params.maxTokens = max(params.maxTokens or 0, 1024)\n        result = await sampling_handler(messages, params)\n    else:\n        raise","preventionTips":["Set a generous maxTokens in sampling params","Inspect finish_reason ('length'/'content_filter') when content is empty","Use the tools path when tool calls, not text, are expected","Retry or fall back to another provider on empty text"],"tags":["openai","sampling","empty-response","max-tokens"],"backgroundTag":"empty-model-response","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}