{"record":{"id":"3a7731e8420fc605","repo":"PrefectHQ/fastmcp","slug":"dict-response-type-cannot-be-empty","errorCode":null,"errorMessage":"Dict response_type cannot be empty.","messagePattern":"Dict response_type cannot be empty\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/elicitation.py","lineNumber":230,"sourceCode":"    if title is not None:\n        value_schema[\"title\"] = title\n    if description is not None:\n        value_schema[\"description\"] = description\n\n\ndef _is_scalar_type(response_type: Any) -> bool:\n    \"\"\"Check if response_type is a scalar type that needs wrapping.\"\"\"\n    return (\n        response_type in {bool, int, float, str}\n        or get_origin(response_type) is Literal\n        or (isinstance(response_type, type) and issubclass(response_type, Enum))\n    )\n\n\ndef _parse_dict_syntax(d: dict[str, Any]) -> ElicitConfig:\n    \"\"\"Parse dict syntax: {\"low\": {\"title\": \"...\"}} -> single-select titled.\"\"\"\n    if not d:\n        raise ValueError(\"Dict response_type cannot be empty.\")\n    enum_schema = _dict_to_enum_schema(d, multi_select=False)\n    return ElicitConfig(\n        schema={\n            \"type\": \"object\",\n            \"properties\": {\"value\": enum_schema},\n            \"required\": [\"value\"],\n        },\n        response_type=None,\n        is_raw=True,\n    )\n\n\ndef _parse_list_syntax(lst: list[Any]) -> ElicitConfig:\n    \"\"\"Parse list patterns: [[...]], [{...}], or [...].\"\"\"\n    # [[\"a\", \"b\", \"c\"]] -> multi-select untitled\n    if (\n        len(lst) == 1\n        and isinstance(lst[0], list)","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/elicitation.py#L212-L248","documentation":"FastMCP supports a dict shorthand for ctx.elicit() response_type to build a single-select titled enum (e.g. {\"low\": {\"title\": \"Low\"}}). Passing an empty dict gives the parser nothing to build an enum schema from, so it raises immediately rather than emitting a degenerate schema to the client.","triggerScenarios":"Calling ctx.elicit(response_type={}) or parse_elicit_response_type({}) — a dict response_type with zero keys.","commonSituations":"Building the options dict dynamically from data (e.g. from a DB or config) that came back empty; a typo like response_type=options where options was never populated.","solutions":["Populate the dict with at least one option before calling ctx.elicit(), e.g. {\"low\": {\"title\": \"Low\"}}","Guard the call: only elicit when the options dict is non-empty, otherwise skip the elicitation or return early","If no options exist, reconsider the flow — eliciting a choice with zero choices is not meaningful"],"exampleFix":"// before\nawait ctx.elicit(response_type={})\n// after\nchoices = {\"low\": {\"title\": \"Low\"}, \"high\": {\"title\": \"High\"}}\nif not choices:\n    raise ValueError(\"No choices available\")\nawait ctx.elicit(response_type=choices)","handlingStrategy":"validation","validationCode":"def validate_options(options):\n    if not isinstance(options, dict) or not options:\n        raise ValueError(\"elicit dict response_type must have at least one option\")\n    return options\n\n# call before eliciting\nvalidate_options(choices)\nawait ctx.elicit(response_type=choices)","typeGuard":"def is_nonempty_str_dict(d: object) -> bool:\n    return isinstance(d, dict) and len(d) > 0","tryCatchPattern":"try:\n    result = await ctx.elicit(response_type=choices)\nexcept ValueError as e:\n    if \"cannot be empty\" in str(e):\n        logger.error(\"elicitation options were empty; skipping prompt\")\n        return None\n    raise","preventionTips":["Never pass a literal {} as response_type","Validate dynamically built option dicts are non-empty before eliciting","Add a unit test covering the empty-options path of your elicitation flow"],"tags":["elicitation","schema","fastmcp","python"],"backgroundTag":"empty-elicitation-options","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}