PrefectHQ/fastmcp · error · ValueError
Cannot add unversioned {type_name} {logical_name!r}: version
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.
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)
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 {type_name} {logical_name!r} (version={
- Version string cannot contain '@' (used as key delimiter): {
- mcp_tool() got unexpected keyword argument(s): {sorted(unkno
- mcp_resource() got unexpected keyword argument(s): {sorted(u
- mcp_prompt() got unexpected keyword argument(s): {sorted(unk
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/0f518bdd820c108d.
Report an issue: GitHub.