PrefectHQ/fastmcp · error · ValueError

Cannot add versioned {type_name} {logical_name!r} (version={

Error message

Cannot add versioned {type_name} {logical_name!r} (version={component.version!r}): an unversioned {type_name} with this name already exists. Either version all components or none.

What it means

FastMCP requires each logical component name to be either entirely versioned or entirely unversioned. Adding a versioned component (version set) when an unversioned component of the same type and name already exists raises ValueError, since the two identity schemes cannot coexist and lookups would be ambiguous.

Source

Thrown at fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py:164

            ValueError: If adding would mix versioned and unversioned components.
        """
        comp_type, logical_name = self._get_component_identity(component)
        is_versioned = component.version is not None

        # Check all existing components of the same type and logical name
        for existing in self._components.values():
            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.

View on GitHub (pinned to 1f02114297)

Solutions

  1. Add a version to the existing unversioned component so both are versioned.
  2. Remove the version from the new component to keep the name unversioned.
  3. Rename one of the components so the logical names don't collide.

Example fix

// before
mcp.add_tool(greet_tool)             # unversioned 'greet'
mcp.add_tool(greet_v2, version='2')  # raises

// after
mcp.add_tool(greet_tool, version='1')
mcp.add_tool(greet_v2, version='2')
Defensive patterns

Strategy: validation

Validate before calling

def assert_version_scheme_consistent(existing_components, new_component):
    same_name = [c for c in existing_components
                 if type(c).__name__.lower() == type(new_component).__name__.lower()
                 and (c.name or c.uri) == (new_component.name or new_component.uri)]
    if same_name:
        existing_versioned = same_name[0].version is not None
        if (new_component.version is not None) != existing_versioned:
            raise ValueError('version all components or none for this name')

Type guard

def version_schemes_match(a, b) -> bool:
    return (a.version is None) == (b.version is None)

Try / catch

try:
    mcp.add_tool(greet_v2, version='2')
except ValueError as e:
    if 'Cannot add versioned' in str(e):
        logging.error('mixing versioned/unversioned for same name — align versions')
    raise

Prevention

When it happens

Trigger: Calling add_tool/add_resource/add_template/add_prompt (or _add_component) with a component whose version is set while a same-name, same-type component with version=None is already registered.

Common situations: Incrementally introducing versioning into an existing app: some tools get version='2.0' while older same-name tools remain unversioned; merging registries from two codebases with different conventions.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/e9d7ff28722039c6. Report an issue: GitHub.