flowable/flowable-engine · error · FlowableIllegalArgumentException

Delegate expression did not resolve to an implementation of

Error message

Delegate expression ${handler.getImplementation()} did not resolve to an implementation of ${FlowableCollectionHandler.class}

What it means

Thrown when resolving a multi-instance collectionHandler whose implementationType is 'delegate-expression': the delegate expression resolved successfully but the resulting object does not implement FlowableCollectionHandler, so the behavior has no way to obtain the collection.

Solutions

  1. Make the delegated class implement FlowableCollectionHandler (with its getCollection/resolveCollection methods) and redeploy/rebuild.
  2. Point the delegate-expression at a bean of the correct type.
  3. If you only need a static/dynamic list, use a plain collection expression or variable instead of a collection handler.
  4. Check the Flowable version: the handler interface package/name changed across versions; align imports with your engine version.
  5. Add a startup-time sanity check (bean instanceof FlowableCollectionHandler) in your Spring configuration.

Example fix

// before
class MyCollectionSupplier implements Supplier<Collection<String>> { ... }
// after
class MyCollectionSupplier implements FlowableCollectionHandler {
    public Collection<?> getCollection(DelegateExecution execution) { ... }
}
Defensive patterns

Strategy: type-guard

Validate before calling

Object bean = applicationContext.getBean("myCollectionHandler");
if (!(bean instanceof FlowableCollectionHandler)) {
    throw new IllegalStateException("collectionHandler delegate must implement FlowableCollectionHandler");
}

Type guard

boolean isFlowableCollectionHandler(Object delegate) {
    return delegate instanceof FlowableCollectionHandler;
}

Try / catch

try {
    return task.execute(execution);
} catch (FlowableIllegalArgumentException ex) {
    if (ex.getMessage().contains("FlowableCollectionHandler")) {
        logger.error("collectionHandler delegate-expression resolved to wrong type: {}", ex.getMessage());
    }
    throw ex;
}

Prevention

When it happens

Trigger: flowable:collectionHandler (or the case-variant) configured as a delegate-expression pointing at a bean/expression that resolves to an arbitrary object not implementing org.flowable.engine.impl.util (FlowableCollectionHandler), e.g. a plain List-producing bean or a wrong class.

Common situations: Delegate class implementing the wrong interface or an older/custom variant; bean registered in the Spring context of the wrong type; refactoring renamed/moved the interface so the class no longer implements it; pointing the delegate-expression at a utility method result instead of a handler bean.

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/05a0f3f1f2e983e5. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java:655

                    activeValue = overrideValueNode.asString();
                }
            }
        }
        return activeValue;
    }

    protected FlowableCollectionHandler createFlowableCollectionHandler(CollectionHandler handler, DelegateExecution execution) {
    	FlowableCollectionHandler collectionHandler = null;

        if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equalsIgnoreCase(handler.getImplementationType())) {
        	collectionHandler = new ClassDelegateCollectionHandler(handler.getImplementation(), null);
        
        } else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equalsIgnoreCase(handler.getImplementationType())) {
        	Object delegate = DelegateExpressionUtil.resolveDelegateExpression(CommandContextUtil.getProcessEngineConfiguration().getExpressionManager().createExpression(handler.getImplementation()), execution);
            if (delegate instanceof FlowableCollectionHandler) {
                collectionHandler = new DelegateExpressionCollectionHandler(execution, CommandContextUtil.getProcessEngineConfiguration().getExpressionManager().createExpression(handler.getImplementation()));   
            } else {
                throw new FlowableIllegalArgumentException("Delegate expression " + handler.getImplementation() + " did not resolve to an implementation of " + FlowableCollectionHandler.class);
            }
        }
        return collectionHandler;
    }

    // Getters and Setters
    // ///////////////////////////////////////////////////////////

    public Expression getLoopCardinalityExpression() {
        return loopCardinalityExpression;
    }

    public void setLoopCardinalityExpression(Expression loopCardinalityExpression) {
        this.loopCardinalityExpression = loopCardinalityExpression;
    }

    public String getCompletionCondition() {
        return completionCondition;

View on GitHub (pinned to d6d39ce1c6)