github/copilot-sdk · error · IllegalArgumentException
Duplicate parameter name ' + param.name() + ' in tool ' +…
Error message
Duplicate parameter name ' + param.name() + ' in tool ' + toolName + '
What it means
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.
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
Example fix
// before
params.add(Param.of("path", String.class));
params.add(Param.of("path", String.class)); // duplicate
// after
params.add(Param.of("path", String.class));
params.add(Param.of("targetPath", String.class)); Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>(); for (Param<?> p : params) { if (!seen.add(p.name())) throw new IllegalStateException("duplicate " + p.name()); } Type guard
boolean namesUnique(List<Param<?>> ps) { return ps.stream().map(Param::name).distinct().count() == ps.size(); } Try / catch
try { schema = ParamSchema.buildSchema(toolName, params); } catch (IllegalArgumentException e) { /* message names the duplicate param and tool */ throw new ToolRegistrationException(toolName, e); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- A Param descriptor is null for tool ' + toolName + '
- Invalid schema JSON for parameter ' + param.name() + ' in…
- Unknown AgentMode value: + value
- Unknown AskUserVariant value: + value
- Unknown AutoTier value: + value
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/354e4cab8541dbb6.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/rpc/ParamSchema.java:79
* zero or more parameter descriptors
* @return a JSON Schema object map with {@code type=object},
* {@code properties}, and {@code required} keys
* @throws IllegalArgumentException
* if a null param or duplicate parameter names are found
*/
static Map<String, Object> buildSchema(String toolName, ObjectMapper mapper, Param<?>... params) {
if (params == null || params.length == 0) {
return Map.of("type", "object", "properties", Map.of(), "required", List.of());
}
// Validate: no null params, no duplicate names
Set<String> seen = new HashSet<>();
for (Param<?> param : params) {
if (param == null) {
throw new IllegalArgumentException("A Param descriptor is null for tool '" + toolName + "'");
}
if (!seen.add(param.name())) {
throw new IllegalArgumentException(
"Duplicate parameter name '" + param.name() + "' in tool '" + toolName + "'");
}
}
List<String> requiredNames = new ArrayList<>();
Map<String, Object> properties = new LinkedHashMap<>();
for (Param<?> param : params) {
Map<String, Object> typeSchema;
if (!param.schema().isEmpty()) {
try {
@SuppressWarnings("unchecked")
Map<String, Object> parsed = mapper.readerFor(Map.class)
.with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)
.with(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS).readValue(param.schema());
typeSchema = parsed;
} catch (Exception e) {
throw new IllegalArgumentException("Invalid schema JSON for parameter '" + param.name()View on GitHub (pinned to cd8cf15dc3)