PrefectHQ/fastmcp · error
$defs collision for '{def_name}': an ArgTransform introduces
Error message
$defs collision for '{def_name}': an ArgTransform introduces a definition with the same name as an existing $defs entry but a different schema. Rename one of the colliding types to avoid the conflict. What it means
This error is raised when a tool-transform ArgTransform extracts nested argument schemas whose $defs contain a definition name that already exists in the parent tool's $defs but with a different schema. Since earlier $ref values point at definitions by name, silently overwriting would corrupt those references, so the transform fails loudly instead.
Source
Thrown at fastmcp_slim/fastmcp/tools/tool_transform.py:707
transform,
old_name in parent_required,
)
if transform_result:
new_name, new_schema, is_required, extracted_defs = transform_result
new_props[new_name] = new_schema
new_to_old[new_name] = old_name
if is_required:
new_required.add(new_name)
# Hoist any $defs introduced by an ArgTransform(type=...) so that
# $ref values like "#/$defs/..." resolve at the schema root.
# Fail loudly on key collisions whose schemas differ, since
# silently overwriting would point earlier $ref values at the
# wrong type. Identical re-introductions are a no-op.
for def_name, def_schema in extracted_defs.items():
existing = parent_defs.get(def_name)
if existing is not None and existing != def_schema:
raise ValueError(
f"$defs collision for '{def_name}': an ArgTransform "
f"introduces a definition with the same name as an "
f"existing $defs entry but a different schema. "
f"Rename one of the colliding types to avoid the "
f"conflict."
)
parent_defs[def_name] = def_schema
schema = {
"type": "object",
"properties": new_props,
# Iterate props (not the set) for deterministic ordering
"required": [p for p in new_props if p in new_required],
"additionalProperties": False,
}
if parent_defs:
schema["$defs"] = parent_defsView on GitHub (pinned to 1f02114297)
Solutions
- Rename one of the colliding Pydantic models/types so each $defs name is unique
- Use ArgTransform to drop or restructure the nested argument that pulls in the colliding definition
- Flatten or inline the nested schema of one tool to avoid emitting a named definition
Example fix
// before
class Filter(BaseModel):
limit: int # collides with parent Filter
// after
class ToolBFilter(BaseModel):
limit: int Defensive patterns
Strategy: validation
Validate before calling
from fastmcp.tools.tool_transform import ArgTransform
# After building the transform, inspect the tool's schema $defs for duplicate names:
import json
schema = json.dumps(transformed_tool.parameters)
assert schema.count('"YourModelName"') <= 1, "rename colliding model" Try / catch
try:
transformed = FastMCPTool.from_tool(tool, transform=...)
except ValueError as e:
if "$defs collision" in str(e):
# rename the colliding type and retry
...
raise Prevention
- Prefix nested model class names per tool (ToolAFilter, ToolBFilter)
- Check $defs names after composing tools in tests
- Avoid reusing generic names like Filter, Config, Options across tools
When it happens
Trigger: Calling an_tool() where the child tool's extracted argument schemas introduce a $defs entry with the same name as an existing parent $defs entry but a different schema body.
Common situations: Two tools composed via from_tool that each define a Pydantic model (or nested schema) with the same class name but different fields; refactoring one model's fields without renaming it; generating tools from separate modules that coincidentally share type names.
Related errors
- Dict response_type cannot be empty.
- Invalid list response_type format. Received: {lst}
- ToolTransform has duplicate target name {target!r}: both {se
- Output schemas must represent object types due to MCP spec l
- forward() can only be called within a transformed tool
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/1cc425c34c6388cb.
Report an issue: GitHub.