PrefectHQ/fastmcp · error · ValueError
Invalid list response_type format. Received: {lst}
Error message
Invalid list response_type format. Received: {lst} What it means
When response_type is a plain list, FastMCP recognizes only three shapes: [["a","b"]] (multi-select untitled), [{"opt": {"title": ...}}] (multi-select titled), and ["a","b"] (single-select untitled). Any other list — mixed types, non-string items, nested dicts not matching the titled pattern — is rejected with this error.
Source
Thrown at fastmcp_slim/fastmcp/server/elicitation.py:287
"required": ["value"],
},
response_type=None,
is_raw=True,
)
# ["a", "b", "c"] -> single-select untitled
if lst and all(isinstance(item, str) for item in lst):
# Construct Literal type from tuple - use cast since we can't construct Literal dynamically
# but we know the values are all strings
choice_literal: type[Any] = cast(type[Any], Literal[tuple(lst)]) # type: ignore[valid-type] # ty:ignore[invalid-type-form]
wrapped = ScalarElicitationType[choice_literal] # type: ignore[valid-type] # ty:ignore[invalid-type-form]
return ElicitConfig(
schema=get_elicitation_schema(wrapped),
response_type=wrapped,
is_raw=False,
)
raise ValueError(f"Invalid list response_type format. Received: {lst}")
def _parse_generic_list(response_type: Any) -> ElicitConfig:
"""Parse list[X] type annotation -> multi-select."""
wrapped = ScalarElicitationType[response_type]
return ElicitConfig(
schema=get_elicitation_schema(wrapped),
response_type=wrapped,
is_raw=False,
)
def _parse_scalar_type(response_type: Any) -> ElicitConfig:
"""Parse scalar types (bool, int, float, str, Literal, Enum)."""
wrapped = ScalarElicitationType[response_type]
return ElicitConfig(
schema=get_elicitation_schema(wrapped),
response_type=wrapped,View on GitHub (pinned to 1f02114297)
Solutions
- Use only string options for the plain-list shorthand, e.g. ["red", "green"]
- For non-string choices, define an Enum or Literal type and pass that as response_type
- For multi-select use the exact nested form [["a","b"]] or [{"opt": {"title": "..."}}]
- Ensure the list is non-empty and its elements are homogeneous strings
Example fix
// before
await ctx.elicit(response_type=[1, 2, 3])
// after
from enum import Enum
class Level(Enum):
ONE = 1
TWO = 2
await ctx.elicit(response_type=Level) Defensive patterns
Strategy: validation
Validate before calling
def validate_list_response_type(options):
if not isinstance(options, list) or not options:
raise ValueError("must be a non-empty list")
ok = (
(len(options) == 1 and isinstance(options[0], list) and options[0]
and all(isinstance(i, str) for i in options[0]))
or (len(options) == 1 and isinstance(options[0], dict) and options[0])
or all(isinstance(i, str) for i in options)
)
if not ok:
raise ValueError(f"unsupported list shape: {options!r}")
return options Type guard
def is_valid_list_shorthand(lst: object) -> bool:
if not isinstance(lst, list) or not lst:
return False
if len(lst) == 1 and isinstance(lst[0], list):
return bool(lst[0]) and all(isinstance(i, str) for i in lst[0])
if len(lst) == 1 and isinstance(lst[0], dict):
return bool(lst[0])
return all(isinstance(i, str) for i in lst) Try / catch
try:
result = await ctx.elicit(response_type=options)
except ValueError as e:
if "Invalid list response_type" in str(e):
logger.error(f"bad options shape: {options!r}; use ['a','b'], [['a','b']], or [{{'opt': {{'title': ...}}}}]")
return None
raise Prevention
- Use only string options in the plain-list shorthand; use Enum/Literal types for non-strings
- Remember the three exact shapes: ["a","b"], [["a","b"]], [{"opt": {"title": ...}}]
- Convert Enum members to strings before building option lists
- Add a test that exercises each list shorthand form
When it happens
Trigger: Passing a list containing non-strings like [1, 2, 3], ["a", 2], [], ["a", {"b": 1}], or a single-element list whose item is neither a non-empty string list nor a non-empty dict.
Common situations: Trying to elicit a numeric choice with [1,2,3]; passing an empty options list; accidentally wrapping options twice; building options from Enum members without converting to strings.
Related errors
- Dict response_type cannot be empty.
- response_title and response_description are only supported w
- Elicitation responses must be serializable as a JSON object
- mcp_tool() got unexpected keyword argument(s): {sorted(unkno
- mcp_resource() got unexpected keyword argument(s): {sorted(u
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/5c3f504d2395ade6.
Report an issue: GitHub.