flowable/flowable-engine · error · FlowableException
couldn't find constructor for ${className} with args ${Array
Error message
couldn't find constructor for ${className} with args ${Arrays.asList(args)} What it means
Thrown when ReflectUtil.instantiate cannot locate any declared constructor on the class matching the supplied argument list. No object is created; Flowable aborts with this message listing the class name and arguments.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/util/ReflectUtil.java:280
private static Method findMethod(Class<? extends Object> clazz, String methodName, Object[] args) {
for (Method method : clazz.getDeclaredMethods()) {
// TODO add parameter matching
if (method.getName().equals(methodName) && matches(method.getParameterTypes(), args)) {
return method;
}
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
return findMethod(superClass, methodName, args);
}
return null;
}
public static Object instantiate(String className, Object[] args) {
Class<?> clazz = loadClass(className);
Constructor<?> constructor = findMatchingConstructor(clazz, args);
if (constructor == null) {
throw new FlowableException("couldn't find constructor for " + className + " with args " + Arrays.asList(args));
}
try {
return constructor.newInstance(args);
} catch (Exception e) {
throw new FlowableException("couldn't find constructor for " + className + " with args " + Arrays.asList(args), e);
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
protected static <T> Constructor<T> findMatchingConstructor(Class<T> clazz, Object[] args) {
for (Constructor constructor : clazz.getDeclaredConstructors()) { // cannot use <?> or <T> due to JDK 5/6 incompatibility
if (matches(constructor.getParameterTypes(), args)) {
return constructor;
}
}
return null;
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify the class name string points to the intended class (check for typos/old FQCN)
- Add a constructor accepting exactly the argument types passed to instantiate
- Change the arguments to match an existing constructor
- Check for class shadowing — an unexpected version of the class may be on the classpath
Example fix
// before
public MyDelegate(String cfg) { ... } // invoked with instantiate("MyDelegate", new Object[]{ 42 })
// after
public MyDelegate(Object cfg) { ... } // or pass matching args: instantiate("MyDelegate", new Object[]{ "cfg" }) Defensive patterns
Strategy: validation
Validate before calling
Class<?> clazz = Class.forName(className);
boolean match = Arrays.stream(clazz.getDeclaredConstructors())
.anyMatch(c -> c.getParameterCount() == args.length);
if (!match) throw new IllegalStateException("no matching constructor on " + className); Try / catch
try {
Object o = ReflectUtil.instantiate(className, args);
} catch (FlowableException e) {
throw new IllegalStateException("Check configured class and its constructors: " + className, e);
} Prevention
- Verify configured class names (FQCN) for typos
- Provide a no-arg constructor on custom delegate/handler classes
- Recheck constructor signatures after refactoring custom classes
When it happens
Trigger: instantiate(className, args) is called where findMatchingConstructor returns null — no declared constructor of the loaded class accepts the given argument types/arity.
Common situations: Custom class configured for engine (e.g. custom job handler, variable type) lacking the expected constructor; class refactored and constructor signature changed; wrong class name string pointing to a different class.
Related errors
- database update java class '${upgradestepClassName}' can't b
- Builder ${clazz} is missing constructor (can't pass features
- Unabled to create ExpressionFactory of type '${clazz.getName
- Could not load class: ${className} (or 'Class not found: ${c
- couldn't find constructor for ${className} with args ${Array
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/52e55d9c472a9e02.
Report an issue: GitHub.