{"record":{"id":"29e30085b5f1e5db","repo":"flowable/flowable-engine","slug":"delegate-expression-expression-did-neither-reso","errorCode":null,"errorMessage":"Delegate expression ${expression} did neither resolve to an implementation of ${ActivityBehavior.class} nor ${JavaDelegate.class}","messagePattern":"Delegate expression (.+?) did neither resolve to an implementation of (.+?) nor (.+?)","errorType":"validation","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java","lineNumber":107,"sourceCode":"                }\n\n                Object delegate = DelegateExpressionUtil.resolveDelegateExpression(expression, execution, fieldDeclarations);\n\n                if (delegate instanceof ActivityBehavior) {\n\n                    if (delegate instanceof AbstractBpmnActivityBehavior) {\n                        ((AbstractBpmnActivityBehavior) delegate).setMultiInstanceActivityBehavior(getMultiInstanceActivityBehavior());\n                    }\n\n                    Context.getProcessEngineConfiguration().getDelegateInterceptor()\n                            .handleInvocation(new ActivityBehaviorInvocation((ActivityBehavior) delegate, activityExecution));\n\n                } else if (delegate instanceof JavaDelegate) {\n                    Context.getProcessEngineConfiguration().getDelegateInterceptor().handleInvocation(new JavaDelegateInvocation((JavaDelegate) delegate, execution));\n                    leave(activityExecution);\n\n                } else {\n                    throw new ActivitiIllegalArgumentException(\"Delegate expression \" + expression + \" did neither resolve to an implementation of \"\n                            + ActivityBehavior.class + \" nor \" + JavaDelegate.class);\n                }\n            } else {\n                leave(activityExecution);\n            }\n        } catch (Exception exc) {\n\n            Throwable cause = exc;\n            BpmnError error = null;\n            while (cause != null) {\n                if (cause instanceof BpmnError) {\n                    error = (BpmnError) cause;\n                    break;\n\n                } else if (cause instanceof RuntimeException) {\n                    if (ErrorPropagation.mapException((RuntimeException) cause, activityExecution, mapExceptions)) {\n                        return;\n                    }","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ServiceTaskDelegateExpressionActivityBehavior.java#L89-L125","documentation":"Thrown when a delegate expression on a service task resolves to an object that is neither an ActivityBehavior nor a JavaDelegate. The engine cannot know how to execute the resolved bean, so it rejects it with this ActivitiIllegalArgumentException before dispatching.","triggerScenarios":"flowable:delegateExpression=\"${someBean}\" where someBean resolves to a plain POJO, a String, or a wrong type (e.g. an Expression-returning bean) that implements neither ActivityBehavior nor JavaDelegate; also occurs when the class was refactored and no longer implements JavaDelegate.","commonSituations":"Spring bean registered with the wrong class or interface after a refactor; typo pointing the delegateExpression at a helper bean instead of the delegate; migrating from Activiti 5 where a custom interface was accepted; using ${} on a method instead of a bean reference (should be flowable:expression).","solutions":["Make the resolved bean implement JavaDelegate (or ActivityBehavior) and rebuild/redeploy","Verify the bean name in delegateExpression points to the intended delegate, not a helper/DTO bean","If you want to call a method on a plain bean, use flowable:expression=\"${bean.method(exec)}\" instead of delegateExpression","Check Spring component scanning so the right class is exposed under that bean name"],"exampleFix":"// before\npublic class ApproveTaskHelper {\n    public void approve(DelegateExecution e) { /* ... */ }\n}\n<serviceTask flowable:delegateExpression=\"${approveTaskHelper}\" />\n// after\npublic class ApproveTaskHelper implements JavaDelegate {\n    public void execute(DelegateExecution e) { /* ... */ }\n}\n<serviceTask flowable:delegateExpression=\"${approveTaskHelper}\" />","handlingStrategy":"validation","validationCode":"Object bean = applicationContext.getBean(\"approveTaskHelper\");\nif (!(bean instanceof JavaDelegate) && !(bean instanceof ActivityBehavior)) {\n    throw new IllegalStateException(\n        \"delegateExpression bean must implement JavaDelegate or ActivityBehavior\");\n}","typeGuard":"public static boolean isValidDelegate(Object o) {\n    return o instanceof JavaDelegate || o instanceof ActivityBehavior;\n}","tryCatchPattern":"try {\n    runtimeService.startProcessInstanceByKey(key, vars);\n} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {\n    if (e.getMessage().contains(\"did neither resolve to an implementation of\")) {\n        // wrong bean type bound to delegateExpression; fix bean wiring\n    } else { throw e; }\n}","preventionTips":["Adopt the convention: delegateExpression targets JavaDelegate beans only; use expression for method calls","Add a startup check (or test) asserting every delegateExpression bean implements JavaDelegate","Grep BPMN files for delegateExpression and verify each bean name exists and its type","After refactoring a delegate class, redeploy the process definition and re-run integration tests"],"tags":["bpmn","service-task","delegate-expression","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}