{"record":{"id":"05a0f3f1f2e983e5","repo":"flowable/flowable-engine","slug":"delegate-expression-handler-getimplementation","errorCode":null,"errorMessage":"Delegate expression ${handler.getImplementation()} did not resolve to an implementation of ${FlowableCollectionHandler.class}","messagePattern":"Delegate expression (.+?) did not resolve to an implementation of (.+?)","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java","lineNumber":655,"sourceCode":"                    activeValue = overrideValueNode.asString();\n                }\n            }\n        }\n        return activeValue;\n    }\n\n    protected FlowableCollectionHandler createFlowableCollectionHandler(CollectionHandler handler, DelegateExecution execution) {\n    \tFlowableCollectionHandler collectionHandler = null;\n\n        if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equalsIgnoreCase(handler.getImplementationType())) {\n        \tcollectionHandler = new ClassDelegateCollectionHandler(handler.getImplementation(), null);\n        \n        } else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equalsIgnoreCase(handler.getImplementationType())) {\n        \tObject delegate = DelegateExpressionUtil.resolveDelegateExpression(CommandContextUtil.getProcessEngineConfiguration().getExpressionManager().createExpression(handler.getImplementation()), execution);\n            if (delegate instanceof FlowableCollectionHandler) {\n                collectionHandler = new DelegateExpressionCollectionHandler(execution, CommandContextUtil.getProcessEngineConfiguration().getExpressionManager().createExpression(handler.getImplementation()));   \n            } else {\n                throw new FlowableIllegalArgumentException(\"Delegate expression \" + handler.getImplementation() + \" did not resolve to an implementation of \" + FlowableCollectionHandler.class);\n            }\n        }\n        return collectionHandler;\n    }\n\n    // Getters and Setters\n    // ///////////////////////////////////////////////////////////\n\n    public Expression getLoopCardinalityExpression() {\n        return loopCardinalityExpression;\n    }\n\n    public void setLoopCardinalityExpression(Expression loopCardinalityExpression) {\n        this.loopCardinalityExpression = loopCardinalityExpression;\n    }\n\n    public String getCompletionCondition() {\n        return completionCondition;","sourceCodeStart":637,"sourceCodeEnd":673,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/MultiInstanceActivityBehavior.java#L637-L673","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make the delegated class implement FlowableCollectionHandler (with its getCollection/resolveCollection methods) and redeploy/rebuild.","Point the delegate-expression at a bean of the correct type.","If you only need a static/dynamic list, use a plain collection expression or variable instead of a collection handler.","Check the Flowable version: the handler interface package/name changed across versions; align imports with your engine version.","Add a startup-time sanity check (bean instanceof FlowableCollectionHandler) in your Spring configuration."],"exampleFix":"// before\nclass MyCollectionSupplier implements Supplier<Collection<String>> { ... }\n// after\nclass MyCollectionSupplier implements FlowableCollectionHandler {\n    public Collection<?> getCollection(DelegateExecution execution) { ... }\n}","handlingStrategy":"type-guard","validationCode":"Object bean = applicationContext.getBean(\"myCollectionHandler\");\nif (!(bean instanceof FlowableCollectionHandler)) {\n    throw new IllegalStateException(\"collectionHandler delegate must implement FlowableCollectionHandler\");\n}","typeGuard":"boolean isFlowableCollectionHandler(Object delegate) {\n    return delegate instanceof FlowableCollectionHandler;\n}","tryCatchPattern":"try {\n    return task.execute(execution);\n} catch (FlowableIllegalArgumentException ex) {\n    if (ex.getMessage().contains(\"FlowableCollectionHandler\")) {\n        logger.error(\"collectionHandler delegate-expression resolved to wrong type: {}\", ex.getMessage());\n    }\n    throw ex;\n}","preventionTips":["Have all collection handler delegates implement FlowableCollectionHandler and verify with a startup assertion.","Align the interface package/name with your engine version (it changed across Flowable releases).","Use plain collection expressions/variables when a handler is unnecessary.","Add a Spring context test asserting the bean type before deployment."],"tags":["bpmn","multi-instance","delegate-expression","collection-handler"],"backgroundTag":"type-mismatch","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T16:30:33.424Z"}