{"record":{"id":"5d81a8372c35d5a2","repo":"PrefectHQ/fastmcp","slug":"messages-must-be-str-or-list-message-got-type-m","errorCode":null,"errorMessage":"messages must be str or list[Message], got {type(messages).__name__}","messagePattern":"messages must be str or list\\[Message\\], got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/prompts/base.py","lineNumber":178,"sourceCode":"        super().__init__(messages=normalized, description=description, meta=meta)\n\n    @staticmethod\n    def _normalize_messages(\n        messages: str | list[Message],\n    ) -> list[Message]:\n        \"\"\"Normalize input to list[Message].\"\"\"\n        if isinstance(messages, str):\n            return [Message(messages)]\n        if isinstance(messages, list):\n            # Validate all items are Message\n            for i, item in enumerate(messages):\n                if not isinstance(item, Message):\n                    raise TypeError(\n                        f\"messages[{i}] must be Message, got {type(item).__name__}. \"\n                        f\"Use Message({item!r}) to wrap the value.\"\n                    )\n            return messages\n        raise TypeError(\n            f\"messages must be str or list[Message], got {type(messages).__name__}\"\n        )\n\n    def to_mcp_prompt_result(self) -> GetPromptResult:\n        \"\"\"Convert to MCP GetPromptResult.\"\"\"\n        mcp_messages = [m.to_mcp_prompt_message() for m in self.messages]\n        return GetPromptResult(\n            description=self.description,\n            messages=mcp_messages,\n            _meta=self.meta,  # type: ignore[call-arg]  # _meta is Pydantic alias for meta field\n        )\n\n\nclass InputRequiredPromptResult(PromptResult):\n    \"\"\"The full result of a single multi-round-trip prompt leg (SEP-2322).\n\n    `InputRequiredResult` is a result type, not a `tools/call` feature: any\n    request may resolve to one. When a prompt returns an `InputRequiredResult`","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/prompts/base.py#L160-L196","documentation":"Prompt._normalize_messages accepts only str or list[Message] for messages. Any other top-level type (dict, tuple, None, list-like objects) raises TypeError naming the actual type received.","triggerScenarios":"Prompt(..., messages={\"role\": \"user\", \"content\": \"hi\"}) (dict), messages=(\"a\",\"b\") (tuple), messages=None, or a non-list sequence.","commonSituations":"Passing chat-completion-style dicts; passing a generator or tuple of Messages; JSON deserialization producing dicts instead of Message objects.","solutions":["Convert dicts to Message objects or use the documented str/list[Message] shapes","Wrap sequence in a list: list(messages)","Build Message objects from deserialized data before constructing Prompt"],"exampleFix":"// before\nPrompt(name=\"p\", messages={\"role\": \"user\", \"content\": \"hi\"})\n// after\nPrompt(name=\"p\", messages=[Message(\"hi\")])","handlingStrategy":"type-guard","validationCode":"def normalize_top_level(msgs) -> list[Message]:\n    if isinstance(msgs, str):\n        return [Message(msgs)]\n    if not isinstance(msgs, list):\n        raise TypeError(\"messages must be str or list[Message]\")\n    return [m if isinstance(m, Message) else Message(m) for m in msgs]","typeGuard":"def is_str_or_message_list(v: object) -> bool:\n    return isinstance(v, (str, list))","tryCatchPattern":"try:\n    prompt = Prompt(name=name, messages=msgs)\nexcept TypeError:\n    prompt = Prompt(name=name, messages=[Message(json.dumps(msgs))])  # or correct the type","preventionTips":["Pass lists, not tuples/dicts/generators","Convert chat-style dicts to Message before constructing Prompt","Add unit tests asserting Prompt construction types"],"tags":["prompts","type-error","validation","python"],"backgroundTag":"wrong-argument-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}