flowable/flowable-engine · error · ActivitiIllegalArgumentException
doesn't implement nor
Error message
%s doesn't implement %s nor %s
What it means
ClassDelegate.getExecutionListenerInstance instantiates the configured delegate class and expects it to implement ExecutionListener or JavaDelegate. If the instantiated class implements neither, an ActivitiIllegalArgumentException is thrown naming the class.
Solutions
- Make the delegate class implement org.activiti.engine.delegate.ExecutionListener (or JavaDelegate)
- Correct the class attribute in the BPMN XML to point at the right class
- Ensure the deployed class version actually implements the interface (check for stale jars)
Example fix
// before
public class MyDelegate {
public void run(DelegateExecution e) { ... }
}
// after
public class MyDelegate implements ExecutionListener {
public void notify(DelegateExecution e) { ... }
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = Class.forName(delegateClassName);
if (!ExecutionListener.class.isAssignableFrom(c) && !JavaDelegate.class.isAssignableFrom(c)) {
throw new IllegalStateException(delegateClassName + " must implement ExecutionListener or JavaDelegate");
} Type guard
static boolean isValidExecutionDelegate(Object o) {
return o instanceof ExecutionListener || o instanceof JavaDelegate;
} Try / catch
try {
runtimeService.signal(executionId);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("doesn't implement")) {
// fix the delegate class in the service task definition
}
} Prevention
- Assert delegate classes implement the right interface in unit tests
- Keep the class attribute consistent with the actual class hierarchy
- Avoid refactoring away interface implementations used by BPMN configs
When it happens
Trigger: A service task or execution listener configured with class='com.example.MyDelegate' whose class implements neither ExecutionListener nor JavaDelegate, resolved during getExecutionListenerInstance at execution time.
Common situations: Wrong class name in the BPMN XML class attribute; refactoring removed the interface implementation; typo'd class pointing at an unrelated helper class.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- doesn't implement
- Custom properties resolver delegate expression " +…
- Delegate expression did not resolve to an implementation of…
- doesn't implement CustomPropertiesResolver
- doesn't implement TransactionDependentExecutionListener
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/beac0f6aad5873f8.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java:110
// Execution listener
@Override
public void notify(DelegateExecution execution) {
if (executionListenerInstance == null) {
executionListenerInstance = getExecutionListenerInstance();
}
Context.getProcessEngineConfiguration()
.getDelegateInterceptor()
.handleInvocation(new ExecutionListenerInvocation(executionListenerInstance, execution));
}
protected ExecutionListener getExecutionListenerInstance() {
Object delegateInstance = instantiateDelegate(className, fieldDeclarations);
if (delegateInstance instanceof ExecutionListener) {
return (ExecutionListener) delegateInstance;
} else if (delegateInstance instanceof JavaDelegate) {
return new ServiceTaskJavaDelegateActivityBehavior((JavaDelegate) delegateInstance, skipExpression);
} else {
throw new ActivitiIllegalArgumentException(delegateInstance.getClass().getName() + " doesn't implement " + ExecutionListener.class + " nor " + JavaDelegate.class);
}
}
// Task listener
@Override
public void notify(DelegateTask delegateTask) {
if (taskListenerInstance == null) {
taskListenerInstance = getTaskListenerInstance();
}
try {
Context.getProcessEngineConfiguration()
.getDelegateInterceptor()
.handleInvocation(new TaskListenerInvocation(taskListenerInstance, delegateTask));
} catch (Exception e) {
throw new ActivitiException("Exception while invoking TaskListener: " + e.getMessage(), e);
}
}
View on GitHub (pinned to d6d39ce1c6)