{"record":{"id":"e6f4a127e5c4f57f","repo":"FasterXML/jackson-databind","slug":"duplicate-creator-property-s-index-s-vs-d-f","errorCode":null,"errorMessage":"Duplicate creator property \"%s\" (index %s vs %d) for type %s ","messagePattern":"Duplicate creator property \"(.+?)\" \\(index (.+?) vs (.+?)\\) for type (.+?) ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/deser/bean/CreatorCollector.java","lineNumber":182,"sourceCode":"\n    public void addPropertyCreator(AnnotatedWithParams creator,\n            boolean explicit, SettableBeanProperty[] properties)\n    {\n        if (verifyNonDup(creator, C_PROPS, explicit)) {\n            // Better ensure we have no duplicate names either...\n            if (properties.length > 1) {\n                HashMap<String, Integer> names = new HashMap<>();\n                for (int i = 0, len = properties.length; i < len; ++i) {\n                    String name = properties[i].getName();\n                    // Need to consider Injectables, which may not have\n                    // a name at all, and need to be skipped\n                    // (same for possible AnySetter)\n                    if (name.isEmpty() && (properties[i].getInjectableValueId() != null)) {\n                        continue;\n                    }\n                    Integer old = names.put(name, Integer.valueOf(i));\n                    if (old != null) {\n                        throw new IllegalArgumentException(\"Duplicate creator property \\\"%s\\\" (index %s vs %d) for type %s \".formatted(\n                                name, old, i, ClassUtil.nameOf(_beanType.getRawClass())));\n                    }\n                }\n            }\n            _propertyBasedArgs = properties;\n        }\n    }\n\n    /*\n    /**********************************************************\n    /* Accessors\n    /**********************************************************\n     */\n\n    public boolean hasDefaultCreator() {\n        return _creators[C_DEFAULT] != null;\n    }\n","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/87876ca5c0569b4933aec2d30d6225e4b9ba3a43/src/main/java/tools/jackson/databind/deser/bean/CreatorCollector.java#L164-L200","documentation":"CreatorCollector detects that two parameters of a single property-based creator (constructor or @JsonCreator factory) share the same JSON name. Each creator parameter must map to a unique incoming property name; a duplicate makes deserialization ambiguous so construction is rejected.","triggerScenarios":"A @JsonCreator constructor/factory with two parameters both annotated @JsonProperty(\"sameName\"); two parameters whose names deduce to the same string; an injectable (@Inject) and a real parameter colliding after name resolution.","commonSituations":"Copy-paste of @JsonProperty names across parameters; kotlin/scala compiler-generated constructors that produce duplicate names; mixing @JsonProperty with @JacksonInject where the injectable lacks a distinct name; refactors that rename parameters but not the @JsonProperty values.","solutions":["Give each creator parameter a distinct @JsonProperty value (or let it derive from the parameter name with -parameters compilation).","Annotate injectable parameters with @JacksonInject and ensure their names do not collide (empty-named injectables are skipped).","If merging two parameters, use @JsonUnwrapped or a nested type instead of duplicating the name.","Recompile with -parameters so Jackson can use the actual parameter names and remove redundant @JsonProperty."],"exampleFix":"// before\n@JsonCreator\npublic Foo(@JsonProperty(\"x\") int a, @JsonProperty(\"x\") int b) {} // duplicate\n\n// after\n@JsonCreator\npublic Foo(@JsonProperty(\"x\") int a, @JsonProperty(\"y\") int b) {}","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (Parameter p : constructor.getParameters()) {\n    String n = jsonNameOf(p);\n    if (n != null && !n.isEmpty() && !seen.add(n)) {\n        throw new IllegalStateException(\"Duplicate creator property: \" + n);\n    }\n}","typeGuard":"// no type guard; duplicate-name check is runtime","tryCatchPattern":"try { mapper.readValue(json, Foo.class); }\ncatch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Duplicate creator property\")) {\n        // rename one of the conflicting @JsonProperty parameters\n    } else throw e;\n}","preventionTips":["Compile with -parameters and rely on actual names; annotate only when overriding.","Annotate @JacksonInject parameters distinctly so they are skipped during the duplicate check."],"tags":["deserialization","creator","constructor","duplicate-property"],"backgroundTag":null,"analyzedSha":"87876ca5c0569b4933aec2d30d6225e4b9ba3a43","analyzedAt":"2026-08-11T12:55:24.033Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}