{"record":{"id":"9448452d5b679852","repo":"alibaba/arthas","slug":"duplicate-tool-name-toolname","errorCode":null,"errorMessage":"Duplicate tool name: ${toolName}","messagePattern":"Duplicate tool name: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/protocol/server/McpServer.java","lineNumber":274,"sourceCode":"\t\t\tthis.taskMessageQueue = taskMessageQueue;\n\t\t\treturn this;\n\t\t}\n\n\t\tprotected void validateTaskConfiguration() {\n\t\t\tboolean hasTaskTools = !this.taskTools.isEmpty();\n\t\t\tboolean hasTaskStore = this.taskStore != null;\n\t\t\t\n\t\t\tif (hasTaskTools && !hasTaskStore) {\n\t\t\t\tthrow new IllegalStateException(\"Task-aware tools registered but no TaskStore configured. \"\n\t\t\t\t\t\t+ \"Add a TaskStore via .taskStore(store) or remove task tools.\");\n\t\t\t}\n\t\t\t// Note: Having taskStore without taskTools is allowed (for future dynamic registration)\n\t\t}\n\n\t\tprivate void assertNoDuplicateTool(String toolName) {\n\t\t\tfor (McpServerFeatures.ToolSpecification tool : this.tools) {\n\t\t\t\tif (tool.getTool().getName().equals(toolName)) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Duplicate tool name: \" + toolName);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (TaskAwareToolSpecification taskTool : this.taskTools) {\n\t\t\t\tif (taskTool.tool().getName().equals(toolName)) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Duplicate tool name: \" + toolName);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic McpNettyServer build() {\n\t\t\tvalidateTaskConfiguration();\n\t\t\t\n\t\t\tObjectMapper mapper = this.objectMapper != null ? this.objectMapper : JsonParser.getObjectMapper();\n\t\t\tAssert.notNull(this.commandExecutor, \"CommandExecutor must be set before building\");\n\t\t\treturn new McpNettyServer(\n\t\t\t\t\tthis.transportProvider, mapper, this.requestTimeout,\n\t\t\t\t\tnew McpServerFeatures.McpServerConfig(this.serverInfo, this.serverCapabilities, this.tools,\n\t\t\t\t\t\t\tthis.taskTools,","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/alibaba/arthas/blob/21cf2e9ba52b305290be7223b980ff504bb9cb5b/arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/protocol/server/McpServer.java#L256-L292","documentation":"Thrown by assertNoDuplicateTool() during the .tools(...) / .tool(...) builder calls when a ToolSpecification name collides with an already-registered regular (non-task) tool. The MCP tools capability requires unique tool names; the check scans the existing this.tools list. It is an IllegalArgumentException at configuration time, before any server starts.","triggerScenarios":"Adding two ToolSpecifications whose getTool().getName() returns the same string via .tools(...) or .tool(...); merging tool lists from modules that did not coordinate names.","commonSituations":"Two plugins defining a tool named identically (e.g. 'execute'); copy-pasted tool specs; default tool names colliding with custom ones.","solutions":["Give each ToolSpecification a globally unique name; namespace by module/feature.","Dedupe the tool list before passing it to the builder.","Catch IllegalArgumentException during registration setup to fail fast with a clear message.","Audit all .tool()/.tools() call sites for name collisions."],"exampleFix":"// before\nspec.tool(toolNamedExecute).tool(otherToolNamedExecute); // throws\n\n// after\nSet<String> names = new HashSet<>();\nfor (var t : allTools) {\n    if (!names.add(t.getTool().getName())) {\n        throw new IllegalStateException(\"Duplicate: \" + t.getTool().getName());\n    }\n}\nspec.tools(allTools);","handlingStrategy":"validation","validationCode":"Set<String> names = new HashSet<>();\nfor (McpServerFeatures.ToolSpecification t : allTools) {\n    if (!names.add(t.getTool().getName())) {\n        throw new IllegalStateException(\"Duplicate tool name: \" + t.getTool().getName());\n    }\n}\nspec.tools(allTools);","typeGuard":null,"tryCatchPattern":"try {\n    spec.tool(newTool);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Duplicate tool name\")) {\n        // rename or skip\n    } else throw e;\n}","preventionTips":["Dedupe the tool list before registering.","Namespace tool names per module.","Unit-test that your tool registry has unique names."],"tags":["mcp","tool","builder","duplicate","configuration","java"],"backgroundTag":null,"analyzedSha":"21cf2e9ba52b305290be7223b980ff504bb9cb5b","analyzedAt":"2026-08-14T00:57:07.243Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}