{"record":{"id":"9dee4e92507db8f1","repo":"PrefectHQ/fastmcp","slug":"component-already-exists-component-key","errorCode":null,"errorMessage":"Component already exists: {component.key}","messagePattern":"Component already exists: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py","lineNumber":190,"sourceCode":"                        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.\n\n        Returns:\n            The component that was added (or existing if on_duplicate=\"ignore\").\n        \"\"\"\n        existing = self._components.get(component.key)\n        if existing:\n            if self._on_duplicate == \"error\":\n                raise ValueError(f\"Component already exists: {component.key}\")\n            elif self._on_duplicate == \"warn\":\n                logger.warning(f\"Component already exists: {component.key}\")\n            elif self._on_duplicate == \"ignore\":\n                return existing  # type: ignore[return-value]  # ty:ignore[invalid-return-type]\n            # \"replace\" and \"warn\" fall through to add\n\n        # Check for versioned/unversioned mixing before adding\n        self._check_version_mixing(component)\n\n        self._components[component.key] = component\n        return component\n\n    def _remove_component(self, key: str) -> None:\n        \"\"\"Remove a component from unified storage.\n\n        Args:\n            key: The prefixed key of the component.\n","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py#L172-L208","documentation":"LocalProvider was configured with on_duplicate='error', and a component with the same key (type + identifier + version) is already registered. Adding it again raises ValueError including the duplicate key, instead of silently replacing or ignoring.","triggerScenarios":"Calling add_tool/add_resource/add_template/add_prompt twice with the same name/uri/version while the provider's on_duplicate policy is 'error'; re-importing/re-running a registration module against a long-lived server object.","commonSituations":"Module-level registrations executed twice (hot reload, notebook re-runs, tests reusing a server fixture); plugin systems registering the same component from two files.","solutions":["Set on_duplicate='replace' (or 'ignore'/'warn') when constructing the provider/server to permit re-registration.","Guard registration so each component is added only once (idempotent init, module-level once-guard).","Bump or vary the component version/name if the duplicate is genuinely a distinct variant."],"exampleFix":"// before\nmcp = FastMCP()  # on_duplicate defaults to 'error'\nmcp.add_tool(my_tool)\nmcp.add_tool(my_tool)  # raises\n\n// after\nfrom fastmcp.server.providers import LocalProvider\nprovider = LocalProvider(on_duplicate='replace')\nmcp.add_provider(provider)\nmcp.add_tool(my_tool)\nmcp.add_tool(my_tool)  # replaces","handlingStrategy":"try-catch","validationCode":"existing_keys = {c.key for c in provider._components.values()}\nif my_tool.key in existing_keys:\n    logging.warning('skipping duplicate registration for %s', my_tool.key)\nelse:\n    mcp.add_tool(my_tool)","typeGuard":"def already_registered(provider, component) -> bool:\n    return component.key in {c.key for c in provider._components.values()}","tryCatchPattern":"try:\n    mcp.add_tool(my_tool)\nexcept ValueError as e:\n    if str(e).startswith('Component already exists'):\n        logging.info('tool already registered: %s', e)\n    else:\n        raise","preventionTips":["Make registration idempotent: guard with a once-flag or check existing keys.","Configure on_duplicate='replace' or 'ignore' when re-registration is expected (tests, hot reload).","Avoid executing registration modules multiple times against the same server instance.","Give distinct variants distinct names or versions instead of re-adding the same key."],"tags":["fastmcp","duplicate-registration","components"],"backgroundTag":"duplicate-component-registration","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}