PrefectHQ/fastmcp · error · TypeError

messages[ ] must be Message or str, got . Use Message( ) to…

Error message

messages[{i}] must be Message or str, got {type(item).__name__}. Use Message({item!r}) to wrap the value.

What it means

Prompt.convert_result accepts only PromptResult, str, or list of Message/str as a render return value. Inside a list, any item that is not a Message or str raises TypeError at that index, prompting you to wrap it with Message(...).

Solutions

  1. Wrap non-str items in Message(...) inside the returned list
  2. Return a plain str or PromptResult instead of a heterogeneous list
  3. Sanitize the list before returning: [it if isinstance(it,(Message,str)) else Message(str(it)) for it in items]

Example fix

// before
return ["hello", {"role": "user", "content": "bye"}]
// after
return [Message("hello"), Message("bye")]
Defensive patterns

Strategy: type-guard

Validate before calling

def safe_render_list(items) -> list:
    out = []
    for it in items:
        if isinstance(it, (Message, str)):
            out.append(it)
        else:
            out.append(Message(str(it)))
    return out

Type guard

def is_message_or_str_list(v: object) -> bool:
    return isinstance(v, list) and all(isinstance(i, (Message, str)) for i in v)

Try / catch

try:
    result = prompt.convert_result(raw)
except TypeError as e:
    raw = [Message(str(x)) for x in raw]
    result = prompt.convert_result(raw)

Prevention

When it happens

Trigger: A prompt's render() returns a list containing ints, dicts, Messages from a different library, tuples, or None — e.g. return ["hi", {"role": "user", "content": "x"}].

Common situations: Returning LLM SDK message dicts directly from render; returning template parts of mixed types; returning results of splitting a string into non-str objects.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at fastmcp_slim/fastmcp/prompts/base.py:340

        if isinstance(raw_value, mcp_types.InputRequiredResult):
            # The prompt asked the client for input (SEP-2322). Wrap it so the
            # ask travels the middleware chain as an ordinary result; the wire
            # handler unwraps it.
            return InputRequiredPromptResult(raw_value)

        if isinstance(raw_value, str):
            return PromptResult(raw_value, description=self.description, meta=self.meta)

        if isinstance(raw_value, list | tuple):
            messages: list[Message] = []
            for i, item in enumerate(raw_value):
                if isinstance(item, Message):
                    messages.append(item)
                elif isinstance(item, str):
                    messages.append(Message(item))
                else:
                    raise TypeError(
                        f"messages[{i}] must be Message or str, got {type(item).__name__}. "
                        f"Use Message({item!r}) to wrap the value."
                    )
            return PromptResult(messages, description=self.description, meta=self.meta)

        raise TypeError(
            f"Prompt must return str, list[Message], or PromptResult, "
            f"got {type(raw_value).__name__}"
        )

    async def _render(
        self,
        arguments: dict[str, Any] | None = None,
    ) -> PromptResult:
        """Server entry point for prompt renders.

        The server calls this method instead of render() directly so that
        subclasses can customize dispatch. For example, FastMCPProviderPrompt

View on GitHub (pinned to 1f02114297)