{"record":{"id":"869d02b4c3168537","repo":"PrefectHQ/fastmcp","slug":"prompt-must-return-str-list-message-or-promptre","errorCode":null,"errorMessage":"Prompt must return str, list[Message], or PromptResult, got {type(raw_value).__name__}","messagePattern":"Prompt must return str, list\\[Message\\], or PromptResult, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/prompts/base.py","lineNumber":346,"sourceCode":"\n        if isinstance(raw_value, str):\n            return PromptResult(raw_value, description=self.description, meta=self.meta)\n\n        if isinstance(raw_value, list | tuple):\n            messages: list[Message] = []\n            for i, item in enumerate(raw_value):\n                if isinstance(item, Message):\n                    messages.append(item)\n                elif isinstance(item, str):\n                    messages.append(Message(item))\n                else:\n                    raise TypeError(\n                        f\"messages[{i}] must be Message or str, got {type(item).__name__}. \"\n                        f\"Use Message({item!r}) to wrap the value.\"\n                    )\n            return PromptResult(messages, description=self.description, meta=self.meta)\n\n        raise TypeError(\n            f\"Prompt must return str, list[Message], or PromptResult, \"\n            f\"got {type(raw_value).__name__}\"\n        )\n\n    async def _render(\n        self,\n        arguments: dict[str, Any] | None = None,\n    ) -> PromptResult:\n        \"\"\"Server entry point for prompt renders.\n\n        The server calls this method instead of render() directly so that\n        subclasses can customize dispatch. For example, FastMCPProviderPrompt\n        overrides this to delegate to child-server middleware.\n        \"\"\"\n        result = await self.render(arguments)\n        return self.convert_result(result)\n\n    def get_span_attributes(self) -> dict[str, Any]:","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/prompts/base.py#L328-L364","documentation":"Prompt.convert_result is the final gate for render() output: only str, list[Message|str], or PromptResult are supported. Any other top-level type (dict, None, int, tuple) raises TypeError stating what the prompt returned and what is allowed.","triggerScenarios":"render() returns None (e.g. a function whose body forgot to return), a dict (chat-style message), a tuple, or an arbitrary object; an async render returning an unexpected type.","commonSituations":"Returning OpenAI/Anthropic response objects directly; render with early-return paths that skip the return statement; migration from another prompt framework with different return conventions.","solutions":["Return one of the supported shapes: a str, a list of Message/str, or a PromptResult","Wrap the object: PromptResult([Message(str(raw_value))]) or extract .content from SDK responses","Audit all return paths in render() to ensure none return None"],"exampleFix":"// before\ndef render(self):\n    result = build_messages()\n    # returns a dict\n    return result\n// after\ndef render(self):\n    result = build_messages()\n    return [Message(m[\"content\"]) for m in result]","handlingStrategy":"type-guard","validationCode":"def ensure_convertible(raw) -> object:\n    if raw is None or isinstance(raw, dict):\n        raise TypeError(\"render must return str, list[Message|str], or PromptResult\")\n    return raw","typeGuard":"def is_valid_render_result(v: object) -> bool:\n    if v is None or isinstance(v, PromptResult) or isinstance(v, str):\n        return isinstance(v, (PromptResult, str))\n    return isinstance(v, list) and all(isinstance(i, (Message, str)) for i in v)","tryCatchPattern":"try:\n    result = prompt.convert_result(raw)\nexcept TypeError as e:\n    logger.error(\"prompt returned unsupported type: %s\", e)\n    result = prompt.convert_result(str(raw))","preventionTips":["Ensure every return path in render() returns a supported type","Never return None implicitly from render()","Unwrap SDK response objects to their string content before returning"],"tags":["prompts","type-error","return-value","python"],"backgroundTag":"wrong-argument-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}