{"record":{"id":"90a208ec64da05cc","repo":"PrefectHQ/fastmcp","slug":"tooltransform-has-duplicate-target-name-target-r","errorCode":null,"errorMessage":"ToolTransform has duplicate target name {target!r}: both {seen_targets[target]!r} and {original_name!r} map to it","messagePattern":"ToolTransform has duplicate target name (.+?): both (.+?) and (.+?) map to it","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/transforms/tool_transform.py","lineNumber":52,"sourceCode":"        \"\"\"Initialize ToolTransform.\n\n        Args:\n            transforms: Map of original tool name → transform config.\n        \"\"\"\n        self._transforms = transforms\n\n        # Build reverse mapping: final_name → original_name\n        self._name_reverse: dict[str, str] = {}\n        for original_name, config in transforms.items():\n            final_name = config.name if config.name else original_name\n            self._name_reverse[final_name] = original_name\n\n        # Validate no duplicate target names\n        seen_targets: dict[str, str] = {}\n        for original_name, config in transforms.items():\n            target = config.name if config.name else original_name\n            if target in seen_targets:\n                raise ValueError(\n                    f\"ToolTransform has duplicate target name {target!r}: \"\n                    f\"both {seen_targets[target]!r} and {original_name!r} map to it\"\n                )\n            seen_targets[target] = original_name\n\n    def __repr__(self) -> str:\n        names = list(self._transforms.keys())\n        if len(names) <= 3:\n            return f\"ToolTransform({names!r})\"\n        return f\"ToolTransform({names[:3]!r}... +{len(names) - 3} more)\"\n\n    async def list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]:\n        \"\"\"Apply transforms to matching tools.\"\"\"\n        result: list[Tool] = []\n        for tool in tools:\n            if tool.name in self._transforms:\n                transformed = self._transforms[tool.name].apply(tool)\n                result.append(transformed)","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/transforms/tool_transform.py#L34-L70","documentation":"ToolTransform validates that every transformed tool maps to a unique public target name. Each entry's target name is its explicit `name` if set, otherwise the original tool name. If two entries resolve to the same target, the transform map would be ambiguous at lookup time, so the constructor raises ValueError immediately.","triggerScenarios":"Calling `ToolTransform({...})` (or a subclass like the renaming transform) with a dict where two entries produce the same target: e.g. two entries renaming different originals to the same new name, or an explicit `name` on one entry colliding with another entry's original tool name.","commonSituations":"Bulk-renaming configs generated by hand or script where a rename accidentally matches an existing tool name; copying a transform config between environments where one tool was renamed upstream; adding a new renamed entry without noticing the target name already exists.","solutions":["Pick a distinct `name` for one of the colliding transform entries so targets are unique.","Remove one of the duplicate entries if it is redundant (e.g. left over from an old config).","Prefix or namespace generated target names (e.g. `api_<tool>`) in scripted configs to avoid accidental collisions."],"exampleFix":"# before\ntransforms = ToolTransform({\n    \"list_items\": ToolTransformConfig(name=\"items\"),\n    \"get_items\": ToolTransformConfig(name=\"items\"),  # duplicate target 'items'\n})\n# after\ntransforms = ToolTransform({\n    \"list_items\": ToolTransformConfig(name=\"list_items_view\"),\n    \"get_items\": ToolTransformConfig(name=\"get_items_view\"),\n})","handlingStrategy":"validation","validationCode":"targets = [(k, c.name or k) for k, c in transforms.items()]\ndups = [t for t in set(x[1] for x in targets) if [x[1] for x in targets].count(t) > 1]\nif dups:\n    raise ValueError(f\"Duplicate transform target names: {dups}\")","typeGuard":null,"tryCatchPattern":"try:\n    t = ToolTransform(transforms)\nexcept ValueError as e:\n    if \"duplicate target name\" in str(e):\n        log.error(f\"Transform config conflict: {e}\")\n        raise SystemExit(2)","preventionTips":["Centralize tool renaming in one config and assert uniqueness in tests.","Namespace scripted target names to avoid accidental collisions.","Lint transform dicts for duplicate resolved targets in CI."],"tags":["python","valueerror","tool-transform","duplicate-name","config"],"backgroundTag":"duplicate-identifier","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}