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

  1. Verify the class name string points to the intended class (check for typos/old FQCN)
  2. Add a constructor accepting exactly the argument types passed to instantiate
  3. Change the arguments to match an existing constructor
  4. 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

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/52e55d9c472a9e02. Report an issue: GitHub.