{"record":{"id":"8880ea33dce5af78","repo":"flowable/flowable-engine","slug":"completing-can-only-be-called-on-a-s-instance","errorCode":null,"errorMessage":"completing() can only be called on a %s instance","messagePattern":"completing\\(\\) can only be called on a (.+?) instance","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java","lineNumber":193,"sourceCode":"        if (activityBehaviorInstance instanceof SignallableActivityBehavior) {\n            ((SignallableActivityBehavior) activityBehaviorInstance).signal(execution, signalName, signalData);\n        } else {\n            throw new ActivitiException(\"signal() can only be called on a \" + SignallableActivityBehavior.class.getName() + \" instance\");\n        }\n    }\n\n    // Subprocess activityBehaviour\n\n    @Override\n    public void completing(DelegateExecution execution, DelegateExecution subProcessInstance) throws Exception {\n        if (activityBehaviorInstance == null) {\n            activityBehaviorInstance = getActivityBehaviorInstance((ActivityExecution) execution);\n        }\n\n        if (activityBehaviorInstance instanceof SubProcessActivityBehavior) {\n            ((SubProcessActivityBehavior) activityBehaviorInstance).completing(execution, subProcessInstance);\n        } else {\n            throw new ActivitiException(\"completing() can only be called on a \" + SubProcessActivityBehavior.class.getName() + \" instance\");\n        }\n    }\n\n    @Override\n    public void completed(ActivityExecution execution) throws Exception {\n        if (activityBehaviorInstance == null) {\n            activityBehaviorInstance = getActivityBehaviorInstance(execution);\n        }\n\n        if (activityBehaviorInstance instanceof SubProcessActivityBehavior) {\n            ((SubProcessActivityBehavior) activityBehaviorInstance).completed(execution);\n        } else {\n            throw new ActivitiException(\"completed() can only be called on a \" + SubProcessActivityBehavior.class.getName() + \" instance\");\n        }\n    }\n\n    protected ActivityBehavior getActivityBehaviorInstance(ActivityExecution execution) {\n        Object delegateInstance = instantiateDelegate(className, fieldDeclarations);","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java#L175-L211","documentation":"ClassDelegate forwards subprocess lifecycle calls to the resolved delegate instance. completing() is only meaningful for a SubProcessActivityBehavior, so when the resolved delegate does not implement that interface, an ActivitiException is thrown with the fully-qualified interface name. It guards the call cast ((SubProcessActivityBehavior) ...) from failing with an opaque ClassCastException.","triggerScenarios":"A subprocess (call-activity/embedded subprocess) whose ClassDelegate's className resolves to a delegate that does not implement SubProcessActivityBehavior, and the subprocess completes causing completing(execution, subProcessInstance) to be invoked.","commonSituations":"Misconfigured subprocess delegate: developer pointed the activity at a plain ActivityBehavior or JavaDelegate; refactoring renamed the SubProcessActivityBehavior implementation; copy-pasted delegate config from a service task into a subprocess boundary event handler.","solutions":["Implement org.activiti.engine.impl.bpmn.behavior.SubProcessActivityBehavior (completing and completed methods) in the configured delegate class.","Check the BPMN XML/bean config so the subprocess activity uses the correct SubProcessActivityBehavior delegate class.","If the delegate is meant to be a simple task, move it out of the subprocess-completion path that triggers completing()."],"exampleFix":"// before\npublic class SubDelegate implements ActivityBehavior { ... }\n// after\npublic class SubDelegate implements SubProcessActivityBehavior {\n  public void completing(ActivityExecution execution, ActivityExecution subProcessInstance) { ... }\n  public void completed(ActivityExecution execution) { ... }\n}","handlingStrategy":"validation","validationCode":"Class<?> clazz = Class.forName(delegateClassName);\nif (!SubProcessActivityBehavior.class.isAssignableFrom(clazz)) {\n  throw new IllegalStateException(delegateClassName + \" must implement SubProcessActivityBehavior\");\n}","typeGuard":"boolean isSubProcessDelegate(Object delegate) { return delegate instanceof SubProcessActivityBehavior; }","tryCatchPattern":"try {\n  classDelegate.completing(execution, subProcessInstance);\n} catch (ActivitiException e) {\n  if (e.getMessage().contains(\"SubProcessActivityBehavior\")) {\n    log.error(\"Wrong delegate class for subprocess activity\", e);\n  } else throw e;\n}","preventionTips":["Validate delegate interfaces at deployment time, not first execution","Use distinct delegate naming conventions for subprocess vs task delegates","Review BPMN XML of subprocess activities after refactors"],"tags":["delegate","subprocess","bpmn","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-14T11:17:12.474Z"}