PrefectHQ/fastmcp · error · TypeError
Elicitation schema field '{prop_name}' has union type '{unio
Error message
Elicitation schema field '{prop_name}' has union type '{union_type}' which is not a primitive type. Only {ALLOWED_TYPES} are allowed in elicitation schemas. What it means
Within a oneOf/anyOf union property, every branch must be an allowed primitive type (string, number, integer, boolean) or a const/enum branch. A union branch with a non-primitive type (object, array, or missing type) is rejected because MCP elicitation clients can only render primitive unions.
Source
Thrown at fastmcp_slim/fastmcp/server/elicitation.py:471
ref_type = ref_def.get("type")
if ref_type in ALLOWED_TYPES:
continue
# If we can't determine what the ref points to, reject it for safety
raise TypeError(
f"Elicitation schema field '{prop_name}' contains a reference '{ref_path}' "
"that could not be validated. Only references to enum types or primitive types are allowed."
)
# Handle union types (oneOf/anyOf)
if "oneOf" in prop_schema or "anyOf" in prop_schema:
union_schemas = prop_schema.get("oneOf", []) + prop_schema.get("anyOf", [])
for union_schema in union_schemas:
# Allow const and enum in unions
if "const" in union_schema or "enum" in union_schema:
continue
union_type = union_schema.get("type")
if union_type not in ALLOWED_TYPES:
raise TypeError(
f"Elicitation schema field '{prop_name}' has union type '{union_type}' which is not "
f"a primitive type. Only {ALLOWED_TYPES} are allowed in elicitation schemas."
)
continue
# Check for arrays before checking primitive types
if prop_type == "array":
items_schema = prop_schema.get("items", {})
if items_schema.get("type") == "object":
raise TypeError(
f"Elicitation schema field '{prop_name}' is an array of objects, but arrays of objects are not allowed. "
"Elicitation schemas must be flat objects with primitive properties only."
)
# Allow arrays with enum patterns (for multi-select)
if "enum" in items_schema:
continue # Allowed: {"type": "array", "items": {"enum": [...]}}
View on GitHub (pinned to 1f02114297)
Solutions
- Restrict unions to primitive branches, e.g. Union[str, int] or Literal values
- Replace Optional[T] where T is complex with a plain primitive or a default value — note type 'null' is not allowed, so avoid Optional[X] unions that emit a null branch
- Model complex alternatives as separate elicitation fields instead of one union property
Example fix
// before field: Union[str, dict] # anyOf with object branch // after field: Union[str, int] # primitive branches only
Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = {"string", "number", "integer", "boolean"}
def check_unions(schema: dict) -> None:
for prop in schema.get("properties", {}).values():
branches = prop.get("anyOf") or prop.get("oneOf") or []
for b in branches:
if "const" in b or "enum" in b:
continue
if b.get("type") not in ALLOWED:
raise TypeError(f"union branch type {b.get('type')!r} not allowed in elicitation") Type guard
def is_primitive_union(prop_schema: dict) -> bool:
branches = prop_schema.get("anyOf") or prop_schema.get("oneOf") or []
return all(
"const" in b or "enum" in b or b.get("type") in {"string", "number", "integer", "boolean"}
for b in branches
) Try / catch
try:
schema = get_elicitation_schema(response_type)
except TypeError as e:
if "union type" in str(e) and "primitive" in str(e):
logger.error("use only primitive (or const/enum) union branches in elicitation models")
return None
raise Prevention
- Keep unions to primitives: Union[str, int], Literal values, Enum values
- Avoid Optional[ComplexType] unions — 'null' and object branches are rejected
- Model each complex alternative as its own flat field instead of a union
- Check generated JSON schemas for anyOf/oneOf branches in CI
When it happens
Trigger: A property like {"anyOf": [{"type": "string"}, {"type": "object"}]} or {"oneOf": [{"type": "array", ...}]} passed through get_elicitation_schema validation.
Common situations: Modeling optional/nullable fields with unions containing null (type 'null' is not in ALLOWED_TYPES); using Union[ModelA, ModelB]; generating schemas from types like Union[str, list[str]].
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Elicitation schema must be an object schema, got type '{sche
- Elicitation schema field '{prop_name}' contains a reference
- Elicitation schema field '{prop_name}' is an array of object
- Elicitation schema field '{prop_name}' is an array, but arra
- Elicitation schema field '{prop_name}' is an object, but nes
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/3023879cd935246c.
Report an issue: GitHub.