flowable/flowable-engine · error · FlowableIllegalArgumentException

Class does not implement FlowableEventListener

Error message

Class <className> does not implement FlowableEventListener

What it means

Thrown by DelegateFlowableEventListener.getDelegateInstance as a FlowableIllegalArgumentException when the configured listener class name instantiates successfully but the resulting object does not implement FlowableEventListener. failOnException is set to true so the failure surfaces instead of being ignored.

Solutions

  1. Make the configured class implement org.flowable.engine.delegate.event.FlowableEventListener
  2. Correct the class name in the listener registration/configuration
  3. Check for mixed Activiti/Flowable imports causing the interface to be missing
  4. Add a startup smoke test that instantiates configured listeners and asserts the interface

Example fix

// before
public class MyListener implements ActivitiEventListener { ... }
// after
public class MyListener implements org.flowable.engine.delegate.event.FlowableEventListener {
    public void onEvent(FlowableEvent event) { ... }
    public boolean isFailOnException() { return false; }
}
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> c = Class.forName(listenerClassName, true, classLoader);
if (!FlowableEventListener.class.isAssignableFrom(c)) {
    throw new IllegalStateException(listenerClassName + " must implement FlowableEventListener");
}

Type guard

static boolean isValidListenerClass(String className) {
    try { return FlowableEventListener.class.isAssignableFrom(Class.forName(className)); }
    catch (ClassNotFoundException e) { return false; }
}

Try / catch

try { runtimeService.startProcessInstanceByKey(key); }
catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("does not implement " + FlowableEventListener.class.getName())) {
        log.error("Configured listener class wrong type: {}", e.getMessage());
    } else throw e;
}

Prevention

When it happens

Trigger: An event listener registered by class name points at a class whose newInstance/objectFactory result is not a FlowableEventListener; getDelegateInstance is called from onEvent during event dispatch.

Common situations: Wrong class name in listener configuration; class refactored to drop the FlowableEventListener interface; confusion between different listener interfaces (e.g. Activiti vs Flowable, or entity vs engine listeners) after a migration.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/DelegateFlowableEventListener.java:64

    @Override
    public boolean isFailOnException() {
        if (delegateInstance != null) {
            return delegateInstance.isFailOnException();
        }
        return failOnException;
    }

    protected FlowableEventListener getDelegateInstance() {
        if (delegateInstance == null) {
            Object instance = ReflectUtil.instantiate(className);
            if (instance instanceof FlowableEventListener) {
                delegateInstance = (FlowableEventListener) instance;
            } else {
                // Force failing of the listener invocation, since the delegate
                // cannot be created
                failOnException = true;
                throw new FlowableIllegalArgumentException("Class " + className + " does not implement " + FlowableEventListener.class.getName());
            }
        }
        return delegateInstance;
    }
}

View on GitHub (pinned to d6d39ce1c6)