{"record":{"id":"6335f70a9235bdd4","repo":"apache/pulsar","slug":"unequal-number-of-params-and-paramtypes-each-para","errorCode":null,"errorMessage":"Unequal number of params and paramTypes. Each param must have a corresponding param type","messagePattern":"Unequal number of params and paramTypes\\. Each param must have a corresponding param type","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/util/Reflections.java","lineNumber":142,"sourceCode":"            }\n            result = meth.newInstance();\n        } catch (InstantiationException ie) {\n            throw new RuntimeException(\"User class must be concrete\", ie);\n        } catch (NoSuchMethodException e) {\n            throw new RuntimeException(\"User class doesn't have such method\", e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(\"User class must have a no-arg constructor\", e);\n        } catch (InvocationTargetException e) {\n            throw new RuntimeException(\"User class constructor throws exception\", e);\n        }\n        return result;\n\n    }\n\n    public static Object createInstance(String userClassName,\n                                        ClassLoader classLoader, Object[] params, Class<?>[] paramTypes) {\n        if (params.length != paramTypes.length) {\n            throw new RuntimeException(\n                    \"Unequal number of params and paramTypes. Each param must have a corresponding param type\");\n        }\n        Class<?> theCls;\n        try {\n            theCls = Class.forName(userClassName, true, classLoader);\n        } catch (ClassNotFoundException | NoClassDefFoundError cnfe) {\n            throw new RuntimeException(\"User class must be in class path\", cnfe);\n        }\n        Object result;\n        try {\n            Constructor<?> meth = constructorCache.get(theCls);\n            if (null == meth) {\n                meth = theCls.getDeclaredConstructor(paramTypes);\n                meth.setAccessible(true);\n                constructorCache.put(theCls, meth);\n            }\n            result = meth.newInstance(params);\n        } catch (InstantiationException ie) {","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/util/Reflections.java#L124-L160","documentation":"The parameterized overload Reflections.createInstance(className, classLoader, params, paramTypes) requires one entry in paramTypes for each entry in params, because it looks up the constructor with getDeclaredConstructor(paramTypes). If the array lengths differ it fails fast with this RuntimeException before doing any reflection.","triggerScenarios":"Calling Reflections.createInstance(userClassName, classLoader, new Object[]{a, b}, new Class<?>[]{A.class}) — params and paramTypes arrays of different length (either direction).","commonSituations":"Programmatically constructing a pluggable class with constructor arguments where one array was updated but not the other; building the arrays in a loop where an argument was conditionally skipped; passing an empty paramTypes with non-empty params.","solutions":["Make params.length == paramTypes.length; add the missing Class entry or remove the extra argument.","Use the exact runtime classes for each argument (e.g. int.class not Integer.class unless the constructor takes Integer).","Double-check conditional code that builds the two arrays so both grow together."],"exampleFix":"// before\ncreateInstance(name, cl, new Object[]{\"s\", 1}, new Class<?>[]{String.class});\n// after\ncreateInstance(name, cl, new Object[]{\"s\", 1}, new Class<?>[]{String.class, int.class});","handlingStrategy":"validation","validationCode":"if (params.length != paramTypes.length)\n    throw new IllegalArgumentException(\"params/paramTypes length mismatch: \"\n        + params.length + \" vs \" + paramTypes.length);\n// optionally verify constructor matchability first:\nClass<?> c = Class.forName(userClassName, true, classLoader);\nc.getDeclaredConstructor(paramTypes);","typeGuard":"static boolean paramsMatchTypes(Object[] params, Class<?>[] paramTypes) {\n    return params != null && paramTypes != null && params.length == paramTypes.length;\n}","tryCatchPattern":"try { return Reflections.createInstance(name, cl, params, paramTypes); }\ncatch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unequal number of params\"))\n        throw new IllegalArgumentException(\"params and paramTypes must be the same length\", e);\n    throw e;\n}","preventionTips":["Build params and paramTypes in the same loop so they stay in sync","Prefer the no-arg createInstance overload when no constructor args are needed","Unit-test reflective construction paths with representative signatures"],"tags":["reflection","argument-mismatch","api-misuse"],"backgroundTag":"argument-count-mismatch","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}