{"record":{"id":"5c3f504d2395ade6","repo":"PrefectHQ/fastmcp","slug":"invalid-list-response-type-format-received-lst","errorCode":null,"errorMessage":"Invalid list response_type format. Received: {lst}","messagePattern":"Invalid list response_type format\\. Received: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/elicitation.py","lineNumber":287,"sourceCode":"                \"required\": [\"value\"],\n            },\n            response_type=None,\n            is_raw=True,\n        )\n\n    # [\"a\", \"b\", \"c\"] -> single-select untitled\n    if lst and all(isinstance(item, str) for item in lst):\n        # Construct Literal type from tuple - use cast since we can't construct Literal dynamically\n        # but we know the values are all strings\n        choice_literal: type[Any] = cast(type[Any], Literal[tuple(lst)])  # type: ignore[valid-type]  # ty:ignore[invalid-type-form]\n        wrapped = ScalarElicitationType[choice_literal]  # type: ignore[valid-type]  # ty:ignore[invalid-type-form]\n        return ElicitConfig(\n            schema=get_elicitation_schema(wrapped),\n            response_type=wrapped,\n            is_raw=False,\n        )\n\n    raise ValueError(f\"Invalid list response_type format. Received: {lst}\")\n\n\ndef _parse_generic_list(response_type: Any) -> ElicitConfig:\n    \"\"\"Parse list[X] type annotation -> multi-select.\"\"\"\n    wrapped = ScalarElicitationType[response_type]\n    return ElicitConfig(\n        schema=get_elicitation_schema(wrapped),\n        response_type=wrapped,\n        is_raw=False,\n    )\n\n\ndef _parse_scalar_type(response_type: Any) -> ElicitConfig:\n    \"\"\"Parse scalar types (bool, int, float, str, Literal, Enum).\"\"\"\n    wrapped = ScalarElicitationType[response_type]\n    return ElicitConfig(\n        schema=get_elicitation_schema(wrapped),\n        response_type=wrapped,","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/elicitation.py#L269-L305","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait ctx.elicit(response_type=[1, 2, 3])\n// after\nfrom enum import Enum\nclass Level(Enum):\n    ONE = 1\n    TWO = 2\nawait ctx.elicit(response_type=Level)","handlingStrategy":"validation","validationCode":"def validate_list_response_type(options):\n    if not isinstance(options, list) or not options:\n        raise ValueError(\"must be a non-empty list\")\n    ok = (\n        (len(options) == 1 and isinstance(options[0], list) and options[0]\n         and all(isinstance(i, str) for i in options[0]))\n        or (len(options) == 1 and isinstance(options[0], dict) and options[0])\n        or all(isinstance(i, str) for i in options)\n    )\n    if not ok:\n        raise ValueError(f\"unsupported list shape: {options!r}\")\n    return options","typeGuard":"def is_valid_list_shorthand(lst: object) -> bool:\n    if not isinstance(lst, list) or not lst:\n        return False\n    if len(lst) == 1 and isinstance(lst[0], list):\n        return bool(lst[0]) and all(isinstance(i, str) for i in lst[0])\n    if len(lst) == 1 and isinstance(lst[0], dict):\n        return bool(lst[0])\n    return all(isinstance(i, str) for i in lst)","tryCatchPattern":"try:\n    result = await ctx.elicit(response_type=options)\nexcept ValueError as e:\n    if \"Invalid list response_type\" in str(e):\n        logger.error(f\"bad options shape: {options!r}; use ['a','b'], [['a','b']], or [{{'opt': {{'title': ...}}}}]\")\n        return None\n    raise","preventionTips":["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"],"tags":["elicitation","schema","fastmcp","python"],"backgroundTag":"invalid-response-type-shape","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}