{"record":{"id":"354e4cab8541dbb6","repo":"github/copilot-sdk","slug":"duplicate-parameter-name-param-name-in-t","errorCode":null,"errorMessage":"Duplicate parameter name ' + param.name() + ' in tool ' + toolName + '","messagePattern":"Duplicate parameter name ' \\+ param\\.name\\(\\) \\+ ' in tool ' \\+ toolName \\+ '","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/rpc/ParamSchema.java","lineNumber":79,"sourceCode":"     *            zero or more parameter descriptors\n     * @return a JSON Schema object map with {@code type=object},\n     *         {@code properties}, and {@code required} keys\n     * @throws IllegalArgumentException\n     *             if a null param or duplicate parameter names are found\n     */\n    static Map<String, Object> buildSchema(String toolName, ObjectMapper mapper, Param<?>... params) {\n        if (params == null || params.length == 0) {\n            return Map.of(\"type\", \"object\", \"properties\", Map.of(), \"required\", List.of());\n        }\n\n        // Validate: no null params, no duplicate names\n        Set<String> seen = new HashSet<>();\n        for (Param<?> param : params) {\n            if (param == null) {\n                throw new IllegalArgumentException(\"A Param descriptor is null for tool '\" + toolName + \"'\");\n            }\n            if (!seen.add(param.name())) {\n                throw new IllegalArgumentException(\n                        \"Duplicate parameter name '\" + param.name() + \"' in tool '\" + toolName + \"'\");\n            }\n        }\n\n        List<String> requiredNames = new ArrayList<>();\n        Map<String, Object> properties = new LinkedHashMap<>();\n\n        for (Param<?> param : params) {\n            Map<String, Object> typeSchema;\n            if (!param.schema().isEmpty()) {\n                try {\n                    @SuppressWarnings(\"unchecked\")\n                    Map<String, Object> parsed = mapper.readerFor(Map.class)\n                            .with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)\n                            .with(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS).readValue(param.schema());\n                    typeSchema = parsed;\n                } catch (Exception e) {\n                    throw new IllegalArgumentException(\"Invalid schema JSON for parameter '\" + param.name()","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/rpc/ParamSchema.java#L61-L97","documentation":"Thrown by ParamSchema.buildSchema when two Param descriptors in the same tool share the same name. Duplicate names would produce ambiguous JSON schema properties and undefined argument binding, so validation rejects the tool registration up front.","triggerScenarios":"Calling buildSchema with a params list where two Params have identical name() values — e.g. copying a Param and forgetting to rename it, or merging parameter lists from two sources.","commonSituations":"Code generation or copy-paste duplication of parameter declarations; combining a base tool's params with an override list that repeats a name; refactors renaming the Java field but not the Param name.","solutions":["Rename one of the duplicate Params so every name in the tool is unique","Deduplicate before building: keep the first (or last) Param per name via a LinkedHashMap","Add a unit test asserting buildSchema succeeds for every registered tool","Catch IllegalArgumentException; the message names the offending parameter and tool"],"exampleFix":"// before\nparams.add(Param.of(\"path\", String.class));\nparams.add(Param.of(\"path\", String.class)); // duplicate\n// after\nparams.add(Param.of(\"path\", String.class));\nparams.add(Param.of(\"targetPath\", String.class));","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>(); for (Param<?> p : params) { if (!seen.add(p.name())) throw new IllegalStateException(\"duplicate \" + p.name()); }","typeGuard":"boolean namesUnique(List<Param<?>> ps) { return ps.stream().map(Param::name).distinct().count() == ps.size(); }","tryCatchPattern":"try { schema = ParamSchema.buildSchema(toolName, params); } catch (IllegalArgumentException e) { /* message names the duplicate param and tool */ throw new ToolRegistrationException(toolName, e); }","preventionTips":["Deduplicate params via a LinkedHashMap keyed by name when merging lists","Rename copied Params immediately after copy-paste","Test that buildSchema succeeds for all registered tools"],"tags":["java","rpc","duplicate","tool-schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}