{"record":{"id":"dda9f5e83ee9901d","repo":"zylon-ai/private-gpt","slug":"duplicate-tool-names-found-in-the-tools-list-prov","errorCode":null,"errorMessage":"Duplicate tool names found in the tools list. Provided tools: {self.tools} Unique tool names: {set(tool_names)}","messagePattern":"Duplicate tool names found in the tools list\\. Provided tools: (.+?) Unique tool names: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"private_gpt/server/chat/chat_models.py","lineNumber":378,"sourceCode":"                        \"Tools are not supported when response_format is set to json_schema\"\n                    )\n                raise ValueError(\n                    \"Tools are not supported when structured output is enabled.\"\n                )\n            if self.mcp_servers:\n                raise ValueError(\n                    \"MCP servers are not supported when structured output is enabled.\"\n                )\n            if system.citations.enabled:\n                raise ValueError(\n                    \"Citations are not supported when structured output is enabled.\"\n                )\n\n        # Check unique tools\n        if self.tools:\n            tool_names = [tool.name for tool in self.tools]\n            if len(tool_names) != len(set(tool_names)):\n                raise ValueError(\n                    \"Duplicate tool names found in the tools list.\"\n                    f\" Provided tools: {self.tools}\"\n                    f\" Unique tool names: {set(tool_names)}\"\n                )\n\n        # Check tool use and result blocks\n        tool_uses_ids: set[str] = set()\n        tool_results_ids: set[str] = set()\n        for message in self.messages:\n            if isinstance(message.content, list):\n                for block in message.content:\n                    if block is None:\n                        raise ValueError(\"Block cannot be None\")\n                    elif isinstance(block, ToolUseBlock):\n                        if message.role != \"assistant\":\n                            raise ValueError(\n                                f\"Tool use blocks can only be used in assistant messages: {message}\"\n                            )","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/chat/chat_models.py#L360-L396","documentation":"ChatBody validates that tool names are unique: two tools with the same name in the tools list make tool resolution ambiguous, so the validator raises with both the full tools list and the unique name set included in the message.","triggerScenarios":"Registering both a built-in tool and a custom tool named 'database_query'; aggregating tools from multiple providers that share names (e.g. two 'search' tools); duplicating a tool entry when merging configs.","commonSituations":"Combining MCP server tools with local tools that collide on names; copy-paste tool definitions; version upgrades that add a tool whose name already exists in user config.","solutions":["Rename one of the colliding tools (names must be unique within a request).","Namespace tools by source when aggregating, e.g. 'mcp_fs_search' vs 'local_search'.","Deduplicate before sending: keep first occurrence per name."],"exampleFix":"# before\ntools = mcp_tools + local_tools  # both contain 'search'\n\n# after\nseen = set()\ntools = [t for t in (mcp_tools + local_tools) if not (t.name in seen or seen.add(t.name))]","handlingStrategy":"validation","validationCode":"names = [t['name'] for t in tools]\nassert len(names) == len(set(names)), f'duplicate tools: {set(n for n in names if names.count(n) > 1)}'","typeGuard":"def tool_names_unique(tools: list[dict]) -> bool:\n    names = [t.get('name') for t in tools]\n    return len(names) == len(set(names))","tryCatchPattern":"except ValidationError as e:\n    if 'Duplicate tool names' in str(e):\n        seen = set(); tools = [t for t in tools if not (t['name'] in seen or seen.add(t['name']))]\n        retry()\n    else:\n        raise","preventionTips":["Namespace tools by source (mcp_fs_search, local_search)","Deduplicate when aggregating tools from multiple providers","Add a startup check that registered tool names are unique"],"tags":["validation","tools","duplicate-names","chat-api"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}