flowable/flowable-engine · error · FlowableIllegalArgumentException

Delegate expression " + expression + " did not resolve to an

Error message

Delegate expression " + expression + " did not resolve to an implementation of " + TaskListener.class

What it means

DelegateExpressionTaskListener resolves the task listener's delegate expression when a task event fires and requires the resolved object to implement TaskListener. Any other type causes notify to throw FlowableIllegalArgumentException. This is the task-scoped counterpart of the execution-listener type check.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/listener/DelegateExpressionTaskListener.java:45

 * @author Joram Barrez
 */
public class DelegateExpressionTaskListener implements TaskListener {

    protected Expression expression;
    private final List<FieldDeclaration> fieldDeclarations;

    public DelegateExpressionTaskListener(Expression expression, List<FieldDeclaration> fieldDeclarations) {
        this.expression = expression;
        this.fieldDeclarations = fieldDeclarations;
    }

    @Override
    public void notify(DelegateTask delegateTask) {
        Object delegate = DelegateExpressionUtil.resolveDelegateExpression(expression, delegateTask, fieldDeclarations);
        if (delegate instanceof TaskListener) {
            CommandContextUtil.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(new TaskListenerInvocation((TaskListener) delegate, delegateTask));
        } else {
            throw new FlowableIllegalArgumentException("Delegate expression " + expression + " did not resolve to an implementation of " + TaskListener.class);
        }
    }

    /**
     * returns the expression text for this task listener. Comes in handy if you want to check which listeners you already have.
     */
    public String getExpressionText() {
        return expression.getExpressionText();
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Make the delegate bean implement org.flowable.engine.delegate.TaskListener and its notify(DelegateTask) method.
  2. Fix the delegateExpression value so it resolves to a genuine TaskListener bean.
  3. If the bean was written as an ExecutionListener, move it to the execution-listener slot or adapt it to TaskListener.
  4. Check imports: TaskListener must be org.flowable.engine.delegate.TaskListener, not a legacy/Activiti one.

Example fix

// before
public class AssignMe {
  public void onCreate(DelegateTask t) { } // plain POJO, not a TaskListener
}
// after
public class AssignMe implements TaskListener {
  @Override
  public void notify(DelegateTask delegateTask) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

Object bean = applicationContext.getBean("myTaskListener");
if (!(bean instanceof org.flowable.engine.delegate.TaskListener)) {
    throw new IllegalStateException("myTaskListener must implement TaskListener");
}

Type guard

public static boolean isTaskListener(Object o) {
    return o instanceof org.flowable.engine.delegate.TaskListener;
}

Try / catch

try {
    taskListener.notify(delegateTask);
} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {
    log.error("Task listener delegateExpression resolved to a non-TaskListener: {}", e.getMessage());
    throw new IllegalArgumentException("Fix taskListener delegateExpression", e);
}

Prevention

When it happens

Trigger: A user task declares <flowable:taskListener event="create" delegateExpression="${someBean}"/>; the bean the expression resolves to does not implement org.flowable.engine.delegate.TaskListener.

Common situations: Bean implements ExecutionListener or JavaDelegate but was attached as a task listener; class implements the old org.activiti TaskListener after migration; expression typo or duplicate bean name resolving to the wrong bean; Spring proxy masking the interface.

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


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