PrefectHQ/fastmcp · error · TypeError
Prompt must return str, list[Message], or PromptResult, got
Error message
Prompt must return str, list[Message], or PromptResult, got {type(raw_value).__name__} What it means
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.
Source
Thrown at fastmcp_slim/fastmcp/prompts/base.py:346
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
overrides this to delegate to child-server middleware.
"""
result = await self.render(arguments)
return self.convert_result(result)
def get_span_attributes(self) -> dict[str, Any]:View on GitHub (pinned to 1f02114297)
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
Example fix
// before
def render(self):
result = build_messages()
# returns a dict
return result
// after
def render(self):
result = build_messages()
return [Message(m["content"]) for m in result] Defensive patterns
Strategy: type-guard
Validate before calling
def ensure_convertible(raw) -> object:
if raw is None or isinstance(raw, dict):
raise TypeError("render must return str, list[Message|str], or PromptResult")
return raw Type guard
def is_valid_render_result(v: object) -> bool:
if v is None or isinstance(v, PromptResult) or isinstance(v, str):
return isinstance(v, (PromptResult, str))
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:
logger.error("prompt returned unsupported type: %s", e)
result = prompt.convert_result(str(raw)) Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.
Related errors
- messages[{i}] must be Message, got {type(item).__name__}. Us
- messages must be str or list[Message], got {type(messages)._
- messages[{i}] must be Message or str, got {type(item).__name
- Expected Prompt or @prompt-decorated function, got {type(pro
- Invalid first argument: {type(name_or_fn)}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/869d02b4c3168537.
Report an issue: GitHub.