flowable/flowable-engine · error · FlowableException

couldn't instantiate class

Error message

couldn't instantiate class ${className}

What it means

ReflectUtil.instantiate creates a new instance of a class by name via its no-arg constructor. Any failure — class not loadable, no default constructor, or constructor throwing — is wrapped in a FlowableException with this message, with the original exception as cause.

Solutions

  1. Read the cause: ClassNotFoundException → add the class to classpath; NoSuchMethodException/InstantiationException → add a public no-arg constructor.
  2. Ensure the instantiated class is public and concrete (not abstract/interface).
  3. Avoid throwing from the constructor; move initialization to an init method.
  4. If using a DI framework, use delegateExpression with a bean reference instead of class name instantiation.
  5. Verify the class name string in configuration.

Example fix

// before
public class MyDelegate {
    public MyDelegate(String name) { ... } // no default ctor
}
// after
public class MyDelegate {
    public MyDelegate() { }
    public MyDelegate(String name) { ... }
}
Defensive patterns

Strategy: try-catch

Validate before calling

Class<?> c = ReflectUtil.loadClass(className);
if (java.lang.reflect.Modifier.isAbstract(c.getModifiers()) || c.isInterface())
    throw new IllegalStateException(className + " is not instantiable");
try { c.getConstructor(); } catch (NoSuchMethodException e) { throw new IllegalStateException(className + " has no no-arg constructor"); }

Try / catch

try {
    Object o = ReflectUtil.instantiate(className);
} catch (FlowableException e) {
    LOGGER.error("Instantiate {} failed: {}", className, e.getCause(), e);
    throw new IllegalStateException("Bad delegate class: " + className, e.getCause());
}

Prevention

When it happens

Trigger: Calling ReflectUtil.instantiate(className) where the class is missing, lacks a public no-argument constructor, is abstract/interface, or its constructor throws an exception.

Common situations: Custom Flowable classes (delegates, listeners, form types) declared by name in configuration that don't have default constructors; constructor does DI or throws during initialization; class not deployed with the app.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/util/ReflectUtil.java:148

            // Try the current Thread context classloader
            classLoader = Thread.currentThread().getContextClassLoader();
            url = classLoader.getResource(name);
            if (url == null) {
                // Finally, try the classloader for this class
                classLoader = ReflectUtil.class.getClassLoader();
                url = classLoader.getResource(name);
            }
        }

        return url;
    }

    public static Object instantiate(String className) {
        try {
            Class<?> clazz = loadClass(className);
            return clazz.getConstructor().newInstance();
        } catch (Exception e) {
            throw new FlowableException("couldn't instantiate class " + className, e);
        }
    }

    public static Object invoke(Object target, String methodName, Object[] args) {
        try {
            Class<? extends Object> clazz = target.getClass();
            Method method = findMethod(clazz, methodName, args);
            method.setAccessible(true);
            return method.invoke(target, args);
        } catch (Exception e) {
            throw new FlowableException("couldn't invoke " + methodName + " on " + target, e);
        }
    }
    
    public static void invokeSetterOrField(Object target, String name, Object value, boolean throwExceptionOnMissingField) {
        Method setterMethod = getSetter(name, target.getClass(), value.getClass());

        if (setterMethod != null) {

View on GitHub (pinned to d6d39ce1c6)