{"record":{"id":"8ddbc5074858e950","repo":"clojure/clojure","slug":"unexpected-number-of-constructor-arguments-to","errorCode":null,"errorMessage":"Unexpected number of constructor arguments to {}: got {}","messagePattern":"Unexpected number of constructor arguments to (.+?): got (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/jvm/clojure/lang/LispReader.java","lineNumber":1487,"sourceCode":"\t\t} else if (form instanceof IPersistentVector) {\n\t\t\tshortForm = true;\n\t\t} else {\n\t\t\tthrow Util.runtimeException(\"Unreadable constructor form starting with \\\"#\" + recordName + \"\\\"\");\n\t\t}\n\n\t\tObject ret = null;\n\t\tConstructor[] allctors = ((Class)recordClass).getConstructors();\n\n\t\tif(shortForm)\n\t\t\t{\n\t        IPersistentVector recordEntries = (IPersistentVector)form;\n\t\t\tboolean ctorFound = false;\n\t\t\tfor (Constructor ctor : allctors)\n\t\t\t\tif(ctor.getParameterTypes().length == recordEntries.count())\n\t\t\t\t\tctorFound = true;\n\n\t\t\tif(!ctorFound)\n\t\t\t\tthrow Util.runtimeException(\"Unexpected number of constructor arguments to \" + recordClass.toString() + \": got \" + recordEntries.count());\n\n\t\t\tret = Reflector.invokeConstructor(recordClass, RT.toArray(recordEntries));\n\t\t\t}\n\t\telse\n\t\t\t{\n\n\t\t\tIPersistentMap vals = (IPersistentMap)form;\n\t\t\tfor(ISeq s = RT.keys(vals); s != null; s = s.next())\n\t\t\t\t{\n\t\t\t\tif(!(s.first() instanceof Keyword))\n\t\t\t\t\tthrow Util.runtimeException(\"Unreadable defrecord form: key must be of type clojure.lang.Keyword, got \" + s.first().toString());\n\t\t\t\t}\n\t\t\tret = Reflector.invokeStaticMethod(recordClass, \"create\", new Object[]{vals});\n\t\t\t}\n\n\t\treturn ret;\n\t}\n}","sourceCodeStart":1469,"sourceCodeEnd":1505,"githubUrl":"https://github.com/clojure/clojure/blob/f3b143341d6efc6428b523b2eaa099a6cc99156e/src/jvm/clojure/lang/LispReader.java#L1469-L1505","documentation":"When reading the short positional form #RecordName[...] the reader scans the record class's constructors for one whose parameter count matches the number of supplied arguments. If no constructor accepts that arity, it throws listing the class and the argument count received. This happens after class lookup succeeds, so the record name is valid but the arity is wrong.","triggerScenarios":"Reading #user.Point[1 2 3] when the defrecord Point has only 2 fields (constructors of arity 2 plus the arity-0 factory), or #user.Point[] with a record having required fields.","commonSituations":"Record definition changed (fields added/removed) after data was serialized; hand-edited serialized records; copy-pasting literals from a differently-versioned namespace.","solutions":["Match the argument count to the record's field count: #user.Point[1 2] for a two-field record.","Reload/redefine the record consistently and re-serialize the data (pr-str) from a live instance.","If extra data must be carried, use the map form #user.Point{:k v} and keep extra keys in the record's extmap-safe behavior, or move them to metadata."],"exampleFix":"// before\n#user.Point[1 2 3] ; Point has 2 fields\n// after\n#user.Point[1 2]","handlingStrategy":"validation","validationCode":"(defn arity-matches? [record-class n]\n  (some #(= (count (.getParameterTypes ^java.lang.reflect.Constructor %)) n)\n        (.getConstructors record-class)))","typeGuard":null,"tryCatchPattern":"(try (read-string lit) (catch RuntimeException e (throw (ex-info \"record arity mismatch\" {:literal lit} e))))","preventionTips":["Regenerate serialized literals whenever defrecord fields change","Keep record serialization and definition in the same versioned artifact","Prefer the map form #Rec{:k v} in serialized data"],"tags":["clojure","reader","records","arity"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"f3b143341d6efc6428b523b2eaa099a6cc99156e","analyzedAt":"2026-09-09T12:04:58.961Z","contentChangedAt":"2026-09-09T12:04:58.961Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}