{"record":{"id":"d8c00811a355478e","repo":"PrefectHQ/fastmcp","slug":"elicitation-schema-must-be-an-object-schema-got-t","errorCode":null,"errorMessage":"Elicitation schema must be an object schema, got type '{schema.get('type')}'. Elicitation schemas are limited to flat objects with primitive properties only.","messagePattern":"Elicitation schema must be an object schema, got type '(.+?)'\\. Elicitation schemas are limited to flat objects with primitive properties only\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/elicitation.py","lineNumber":415,"sourceCode":"\n    This ensures the schema is compatible with MCP elicitation requirements:\n    - Must be an object schema\n    - Must only contain primitive field types (string, number, integer, boolean)\n    - Must be flat (no nested objects or arrays of objects)\n    - Allows const fields (for Literal types) and enum fields (for Enum types)\n    - Only primitive types and their nullable variants are allowed\n\n    Args:\n        schema: The JSON schema to validate\n\n    Raises:\n        TypeError: If the schema doesn't meet MCP elicitation requirements\n    \"\"\"\n    ALLOWED_TYPES = {\"string\", \"number\", \"integer\", \"boolean\"}\n\n    # Check that the schema is an object\n    if schema.get(\"type\") != \"object\":\n        raise TypeError(\n            f\"Elicitation schema must be an object schema, got type '{schema.get('type')}'. \"\n            \"Elicitation schemas are limited to flat objects with primitive properties only.\"\n        )\n\n    properties = schema.get(\"properties\", {})\n\n    for prop_name, prop_schema in properties.items():\n        prop_type = prop_schema.get(\"type\")\n\n        # Handle nullable types\n        if isinstance(prop_type, list):\n            if \"null\" in prop_type:\n                prop_type = [t for t in prop_type if t != \"null\"]\n                if len(prop_type) == 1:\n                    prop_type = prop_type[0]\n        elif prop_schema.get(\"nullable\", False):\n            continue  # Nullable with no other type is fine\n","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/elicitation.py#L397-L433","documentation":"MCP elicitation only supports top-level object JSON schemas whose properties are primitives. validate_elicitation_json_schema checks schema['type'] == 'object' first; anything else (string, array, no type, etc.) is rejected with this TypeError before the elicitation is sent to the client.","triggerScenarios":"Defining an elicitation response type whose generated JSON schema is not an object — e.g. response_type=str (via a path that skips wrapping), a Pydantic RootModel, or a hand-built schema dict like {\"type\": \"string\"} passed through get_elicitation_schema.","commonSituations":"Hand-rolling elicitation schemas and forgetting to wrap the primitive in an object with properties; using RootModel or a NewType that collapses to a scalar schema; a library upgrade changing how types are wrapped.","solutions":["Wrap the value in a BaseModel or dataclass so the schema is a flat object with primitive fields","Use the scalar shorthand forms (str, bool, Literal, Enum, dict/list syntax) which FastMCP wraps into an object automatically","If passing a schema dict directly, make it {\"type\": \"object\", \"properties\": {...}}"],"exampleFix":"// before\nschema = {\"type\": \"string\"}\n// after\nfrom pydantic import BaseModel\nclass Answer(BaseModel):\n    name: str\nawait ctx.elicit(response_type=Answer)","handlingStrategy":"validation","validationCode":"def ensure_object_schema(schema: dict) -> dict:\n    if schema.get(\"type\") != \"object\":\n        raise TypeError(f\"elicitation schema must be an object, got {schema.get('type')!r}\")\n    return schema\n\nensure_object_schema(get_elicitation_schema(MyModel))","typeGuard":"def is_object_schema(schema: object) -> bool:\n    return isinstance(schema, dict) and schema.get(\"type\") == \"object\"","tryCatchPattern":"try:\n    schema = get_elicitation_schema(response_type)\nexcept TypeError as e:\n    if \"must be an object schema\" in str(e):\n        logger.error(\"wrap scalar/root types in a BaseModel or use the scalar shorthand\")\n        return None\n    raise","preventionTips":["Always define elicitation response types as flat BaseModels/dataclasses or use the scalar shorthand (bool, str, Literal, Enum, dict/list)","Avoid RootModel and bare scalar types that generate non-object schemas","If passing schema dicts manually, wrap primitives in {\"type\": \"object\", \"properties\": {...}}","Validate schemas in CI before deploying elicitation tools"],"tags":["elicitation","json-schema","schema-validation","fastmcp"],"backgroundTag":"schema-validation-failed","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}