{"record":{"id":"e9d7ff28722039c6","repo":"PrefectHQ/fastmcp","slug":"cannot-add-versioned-type-name-logical-name-r","errorCode":null,"errorMessage":"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.","messagePattern":"Cannot add versioned (.+?) (.+?) \\(version=(.+?)\\): an unversioned (.+?) with this name already exists\\. Either version all components or none\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py","lineNumber":164,"sourceCode":"            ValueError: If adding would mix versioned and unversioned components.\n        \"\"\"\n        comp_type, logical_name = self._get_component_identity(component)\n        is_versioned = component.version is not None\n\n        # Check all existing components of the same type and logical name\n        for existing in self._components.values():\n            if not isinstance(existing, comp_type):\n                continue\n\n            _, existing_name = self._get_component_identity(existing)\n            if existing_name != logical_name:\n                continue\n\n            existing_versioned = existing.version is not None\n            if is_versioned != existing_versioned:\n                type_name = comp_type.__name__.lower()\n                if is_versioned:\n                    raise ValueError(\n                        f\"Cannot add versioned {type_name} {logical_name!r} \"\n                        f\"(version={component.version!r}): an unversioned \"\n                        f\"{type_name} with this name already exists. \"\n                        f\"Either version all components or none.\"\n                    )\n                else:\n                    raise ValueError(\n                        f\"Cannot add unversioned {type_name} {logical_name!r}: \"\n                        f\"versioned {type_name}s with this name already exist \"\n                        f\"(e.g., version={existing.version!r}). \"\n                        f\"Either version all components or none.\"\n                    )\n\n    def _add_component(self, component: _C) -> _C:\n        \"\"\"Add a component to unified storage.\n\n        Args:\n            component: The component to add.","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py#L146-L182","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add a version to the existing unversioned component so both are versioned.","Remove the version from the new component to keep the name unversioned.","Rename one of the components so the logical names don't collide."],"exampleFix":"// before\nmcp.add_tool(greet_tool)             # unversioned 'greet'\nmcp.add_tool(greet_v2, version='2')  # raises\n\n// after\nmcp.add_tool(greet_tool, version='1')\nmcp.add_tool(greet_v2, version='2')","handlingStrategy":"validation","validationCode":"def assert_version_scheme_consistent(existing_components, new_component):\n    same_name = [c for c in existing_components\n                 if type(c).__name__.lower() == type(new_component).__name__.lower()\n                 and (c.name or c.uri) == (new_component.name or new_component.uri)]\n    if same_name:\n        existing_versioned = same_name[0].version is not None\n        if (new_component.version is not None) != existing_versioned:\n            raise ValueError('version all components or none for this name')","typeGuard":"def version_schemes_match(a, b) -> bool:\n    return (a.version is None) == (b.version is None)","tryCatchPattern":"try:\n    mcp.add_tool(greet_v2, version='2')\nexcept ValueError as e:\n    if 'Cannot add versioned' in str(e):\n        logging.error('mixing versioned/unversioned for same name — align versions')\n    raise","preventionTips":["Adopt one convention: either version every component or none.","Keep versions in a single registry/config module so they stay consistent.","Add a startup test that registers all components to catch mixing early."],"tags":["fastmcp","versioning","registration-conflict"],"backgroundTag":"version-scheme-mixing","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}