PrefectHQ/fastmcp · error · ValueError
Cannot add unversioned
Error message
Cannot add unversioned {type_name} {logical_name!r}: versioned {type_name}s with this name already exist (e.g., version={existing.version!r}). Either version all components or none. What it means
The mirror case of version-mixing: registering an unversioned component when versioned components of the same type and logical name already exist raises ValueError, because unversioned and versioned identities for the same name cannot coexist.
Solutions
- Assign a version to the new component to match the existing scheme.
- Remove the versioned components if you intend to go back to unversioned.
- Rename the new component to avoid the logical-name collision.
Example fix
// before mcp.add_tool(greet_v1, version='1') mcp.add_tool(greet_simple) # raises // after mcp.add_tool(greet_v1, version='1') mcp.add_tool(greet_simple, version='1')
Defensive patterns
Strategy: validation
Validate before calling
def assert_unversioned_allowed(existing_components, new_component):
same_name = [c for c in existing_components
if (c.name or c.uri) == (new_component.name or new_component.uri)]
if any(c.version is not None for c in same_name) and new_component.version is None:
raise ValueError('existing components are versioned; assign a version') Type guard
def version_schemes_match(a, b) -> bool:
return (a.version is None) == (b.version is None) Try / catch
try:
mcp.add_tool(legacy_tool)
except ValueError as e:
if 'Cannot add unversioned' in str(e):
logging.error('name is versioned; register with version=...')
raise Prevention
- Version every variant of a given component name once you start versioning.
- Migrate legacy unversioned registrations in the same change that introduces versions.
- Keep one canonical registration module to avoid divergent schemes.
When it happens
Trigger: Calling add_tool/add_resource/add_prompt/add_template with a component lacking a version while versioned components with the same name are already registered.
Common situations: Adding a legacy unversioned copy of a tool that was already upgraded to versioned; replaying old registration code against a server that now versions its components.
Related errors
- Cannot add versioned
- Version string cannot contain '@' (used as key delimiter)
- Amount must be at least 1
- cache_scope requires cache_ttl; a scope without a TTL does…
- Cannot specify both a name as first argument and as keyword…
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/0f518bdd820c108d.
Report an issue: GitHub.
Appendix: source
Thrown at fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py:171
if not isinstance(existing, comp_type):
continue
_, existing_name = self._get_component_identity(existing)
if existing_name != logical_name:
continue
existing_versioned = existing.version is not None
if is_versioned != existing_versioned:
type_name = comp_type.__name__.lower()
if is_versioned:
raise ValueError(
f"Cannot add versioned {type_name} {logical_name!r} "
f"(version={component.version!r}): an unversioned "
f"{type_name} with this name already exists. "
f"Either version all components or none."
)
else:
raise ValueError(
f"Cannot add unversioned {type_name} {logical_name!r}: "
f"versioned {type_name}s with this name already exist "
f"(e.g., version={existing.version!r}). "
f"Either version all components or none."
)
def _add_component(self, component: _C) -> _C:
"""Add a component to unified storage.
Args:
component: The component to add.
Returns:
The component that was added (or existing if on_duplicate="ignore").
"""
existing = self._components.get(component.key)
if existing:
if self._on_duplicate == "error":View on GitHub (pinned to 1f02114297)