PrefectHQ/fastmcp · error · TypeError
Elicitation schema field '{prop_name}' contains a reference
Error message
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. What it means
Elicitation schemas may contain $ref pointers only when they resolve to enum or primitive-typed definitions. If a property's $ref cannot be resolved (missing $defs entry, ref to a nested object/array, or a ref the validator can't trace), the validator rejects it defensively rather than sending an unverifiable schema to the client.
Source
Thrown at fastmcp_slim/fastmcp/server/elicitation.py:457
if "enum" in prop_schema:
continue # enum fields are allowed regardless of type
# Handle references to definitions (like Enum types)
if "$ref" in prop_schema:
# Get the referenced definition
ref_path = prop_schema["$ref"]
if ref_path.startswith("#/$defs/"):
def_name = ref_path[8:] # Remove "#/$defs/" prefix
ref_def = schema.get("$defs", {}).get(def_name, {})
# If the referenced definition has an enum, it's allowed
if "enum" in ref_def:
continue
# If the referenced definition has a type that's allowed, it's allowed
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."
)
continueView on GitHub (pinned to 1f02114297)
Solutions
- Ensure every $ref resolves to a $defs entry with an allowed primitive type or an enum definition
- Inline the enum/primitive directly in the property instead of using $ref
- Use FastMCP's schema generation (Pydantic models / shorthand forms) rather than hand-built $defs — its generator inlines enums automatically
- Run compress_schema or equivalent before validation if composing schemas programmatically
Example fix
// before
{"properties": {"color": {"$ref": "#/$defs/Missing"}}}
// after
{"properties": {"color": {"type": "string", "enum": ["red", "blue"]}}} Defensive patterns
Strategy: validation
Validate before calling
def check_refs(schema: dict) -> None:
defs = schema.get("$defs", {})
for prop in schema.get("properties", {}).values():
ref = prop.get("$ref")
if not ref:
continue
name = ref.rsplit("/", 1)[-1]
target = defs.get(name, {})
if target.get("type") not in {"string", "number", "integer", "boolean"} and "enum" not in target:
raise TypeError(f"ref {ref} must resolve to a primitive or enum definition") Type guard
def ref_is_resolvable_primitive(schema: dict, ref_path: str) -> bool:
if not ref_path.startswith("#/$defs/"):
return False
target = schema.get("$defs", {}).get(ref_path.rsplit("/", 1)[-1], {})
return target.get("type") in {"string", "number", "integer", "boolean"} or "enum" in target Try / catch
try:
schema = get_elicitation_schema(response_type)
except TypeError as e:
if "could not be validated" in str(e) and "$ref" in str(e) or "reference" in str(e):
logger.error("inline your enum/primitive instead of using $ref")
return None
raise Prevention
- Avoid hand-built $defs; let FastMCP's generator inline enums automatically
- If composing schemas, resolve and inline all refs before validation
- Only reference Enum types or primitive-typed definitions
- After schema compression/post-processing, re-validate refs still resolve
When it happens
Trigger: A property schema like {"$ref": "#/$defs/Foo"} where $defs lacks Foo, or where the resolved definition has no 'type' and no enum/const, during get_elicitation_schema validation.
Common situations: Manually composing schemas with shared $defs; post-processing/compressing Pydantic schemas so refs dangle; referencing a BaseModel (object) instead of an Enum; schema tooling rewriting ref paths.
Related errors
- Elicitation schema must be an object schema, got type '{sche
- Elicitation schema field '{prop_name}' has union type '{unio
- 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/0031c71b38ef38ca.
Report an issue: GitHub.