flowable/flowable-engine · error · FlowableIllegalArgumentException
${className} does not implement the ${CmmnTriggerableActivit
Error message
${className} does not implement the ${CmmnTriggerableActivityBehavior.class} interface What it means
Flowable's CMMN engine instantiates a custom class-delegate for a plan item and needs to call trigger() on it, which requires the class to implement CmmnTriggerableActivityBehavior. When the configured className instantiates fine but does not implement that interface, Flowable refuses to cast it and throws this FlowableIllegalArgumentException. It exists to give a clear message instead of a ClassCastException deep inside the engine.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/delegate/CmmnClassDelegate.java:71
this.fieldExtensions = fieldExtensions;
}
@Override
public void execute(DelegatePlanItemInstance planItemInstance) {
if (activityBehaviorInstance == null) {
activityBehaviorInstance = getCmmnActivityBehavior(className);
}
activityBehaviorInstance.execute(planItemInstance);
}
@Override
public void trigger(DelegatePlanItemInstance planItemInstance) {
if (activityBehaviorInstance == null) {
activityBehaviorInstance = getCmmnActivityBehavior(className);
}
if (!(activityBehaviorInstance instanceof CmmnTriggerableActivityBehavior)) {
throw new FlowableIllegalArgumentException(className + " does not implement the "
+ CmmnTriggerableActivityBehavior.class + " interface");
}
((CmmnTriggerableActivityBehavior) activityBehaviorInstance).trigger(planItemInstance);
}
protected CmmnActivityBehavior getCmmnActivityBehavior(String className) {
Object instance = instantiate(className);
applyFieldExtensions(fieldExtensions, instance, false);
if (instance instanceof PlanItemJavaDelegate) {
return new PlanItemJavaDelegateActivityBehavior((PlanItemJavaDelegate) instance);
} else if (instance instanceof PlanItemFutureJavaDelegate) {
return new PlanItemFutureJavaDelegateActivityBehavior((PlanItemFutureJavaDelegate) instance);
} else if (instance instanceof CmmnTriggerableActivityBehavior) {
return (CmmnTriggerableActivityBehavior) instance;View on GitHub (pinned to d6d39ce1c6)
Solutions
- Make the configured class implement CmmnTriggerableActivityBehavior (add trigger(DelegatePlanItemInstance) plus execute).
- If triggering is not needed, change the case definition so the plan item is never triggered with this class, or use a delegate that only needs execute.
- Check the CMMN model XML: the flowable:class attribute of the task/plan item must reference the fully-qualified triggerable class.
- Ensure the classpath resolves the intended class, not a stale/old version without the interface.
Example fix
// before
public class MyTaskBehavior implements CmmnActivityBehavior {
public void execute(CmmnActivityExecutionContext context) { ... }
}
// after
public class MyTaskBehavior implements CmmnTriggerableActivityBehavior {
public void execute(CmmnActivityExecutionContext context) { ... }
public void trigger(DelegatePlanItemInstance planItemInstance) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = Class.forName(className);
if (!org.flowable.cmmn.api.delegate.CmmnTriggerableActivityBehavior.class.isAssignableFrom(c)) {
throw new IllegalStateException(className + " must implement CmmnTriggerableActivityBehavior");
} Type guard
boolean isTriggerable(Object b) { return b instanceof org.flowable.cmmn.api.delegate.CmmnTriggerableActivityBehavior; } Try / catch
try {
behavior.trigger(planItemInstance);
} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {
if (e.getMessage().contains("does not implement")) { log.error("Bad delegate class: {}", e.getMessage()); }
throw e;
} Prevention
- Add a startup test that instantiates every flowable:class referenced in your CMMN models and asserts its interfaces.
- Never reuse BPMN JavaDelegates as CMMN plan item classes.
- If the plan item can be triggered, always implement the triggerable interface up front.
When it happens
Trigger: A plan item (e.g. a task/human task/mail task custom behavior) is configured with flowable:class pointing to a class that implements CmmnActivityBehavior or nothing relevant, but not CmmnTriggerableActivityBehavior, and the engine calls trigger(DelegatePlanItemInstance) on the delegate (typically when a plan item is triggered, e.g. a repeat or reaction to another plan item completing).
Common situations: Developers reuse a non-triggerable behavior class (or a plain JavaDelegate from the BPMN engine) in a CMMN case that later gets triggered; renaming/refactoring a class so it no longer implements the triggerable interface; copying a BPMN listener class into CMMN config.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- ${className} does not implement the ${CmmnActivityBehavior.c
- ${delegateInstance.getClass().getName()} doesn't implement $
- ${delegateInstance.getClass().getName()} doesn't implement $
- ${delegateInstance.getClass().getName()} doesn't implement $
- ${delegateInstance.getClass().getName()} doesn't implement $
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/4970a79e46df7772.
Report an issue: GitHub.