apache/pulsar · error · RuntimeException
Unequal number of params and paramTypes. Each param must hav
Error message
Unequal number of params and paramTypes. Each param must have a corresponding param type
What it means
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.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/Reflections.java:142
}
result = meth.newInstance();
} catch (InstantiationException ie) {
throw new RuntimeException("User class must be concrete", ie);
} catch (NoSuchMethodException e) {
throw new RuntimeException("User class doesn't have such method", e);
} catch (IllegalAccessException e) {
throw new RuntimeException("User class must have a no-arg constructor", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("User class constructor throws exception", e);
}
return result;
}
public static Object createInstance(String userClassName,
ClassLoader classLoader, Object[] params, Class<?>[] paramTypes) {
if (params.length != paramTypes.length) {
throw new RuntimeException(
"Unequal number of params and paramTypes. Each param must have a corresponding param type");
}
Class<?> theCls;
try {
theCls = Class.forName(userClassName, true, classLoader);
} catch (ClassNotFoundException | NoClassDefFoundError cnfe) {
throw new RuntimeException("User class must be in class path", cnfe);
}
Object result;
try {
Constructor<?> meth = constructorCache.get(theCls);
if (null == meth) {
meth = theCls.getDeclaredConstructor(paramTypes);
meth.setAccessible(true);
constructorCache.put(theCls, meth);
}
result = meth.newInstance(params);
} catch (InstantiationException ie) {View on GitHub (pinned to 820761864e)
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.
Example fix
// before
createInstance(name, cl, new Object[]{"s", 1}, new Class<?>[]{String.class});
// after
createInstance(name, cl, new Object[]{"s", 1}, new Class<?>[]{String.class, int.class}); Defensive patterns
Strategy: validation
Validate before calling
if (params.length != paramTypes.length)
throw new IllegalArgumentException("params/paramTypes length mismatch: "
+ params.length + " vs " + paramTypes.length);
// optionally verify constructor matchability first:
Class<?> c = Class.forName(userClassName, true, classLoader);
c.getDeclaredConstructor(paramTypes); Type guard
static boolean paramsMatchTypes(Object[] params, Class<?>[] paramTypes) {
return params != null && paramTypes != null && params.length == paramTypes.length;
} Try / catch
try { return Reflections.createInstance(name, cl, params, paramTypes); }
catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unequal number of params"))
throw new IllegalArgumentException("params and paramTypes must be the same length", e);
throw e;
} Prevention
- 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
When it happens
Trigger: Calling Reflections.createInstance(userClassName, classLoader, new Object[]{a, b}, new Class<?>[]{A.class}) — params and paramTypes arrays of different length (either direction).
Common situations: 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.
Related errors
- Failed to load an authorization provider.
- Failed to instantiate ${className}
- Exception caused while converting configuration: ${message}
- Failed to compute configuration overrides
- Cannot disable validation of default values
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/6335f70a9235bdd4.
Report an issue: GitHub.