flowable/flowable-engine · error · FlowableException
completing() can only be called on a SubProcessActivityBehav
Error message
completing() can only be called on a SubProcessActivityBehavior instance for + execution
What it means
When a subprocess (typically an ad-hoc or custom subprocess) completes, ClassDelegate.completing() delegates to the resolved behavior only if it implements SubProcessActivityBehavior; otherwise a FlowableException is thrown. The completing()/completed() callbacks exist only for subprocess behaviors, so Flowable rejects calls routed through a non-subprocess delegate.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/ClassDelegate.java:256
}
}
} else {
throw new FlowableException("signal() can only be called on a " + TriggerableActivityBehavior.class.getName() + " instance for " + execution);
}
}
// Subprocess activityBehaviour
@Override
public void completing(DelegateExecution execution, DelegateExecution subProcessInstance) throws Exception {
if (activityBehaviorInstance == null) {
activityBehaviorInstance = getActivityBehaviorInstance();
}
if (activityBehaviorInstance instanceof SubProcessActivityBehavior) {
((SubProcessActivityBehavior) activityBehaviorInstance).completing(execution, subProcessInstance);
} else {
throw new FlowableException("completing() can only be called on a " + SubProcessActivityBehavior.class.getName() + " instance for " + execution);
}
}
@Override
public void completed(DelegateExecution execution) throws Exception {
if (activityBehaviorInstance == null) {
activityBehaviorInstance = getActivityBehaviorInstance();
}
if (activityBehaviorInstance instanceof SubProcessActivityBehavior) {
((SubProcessActivityBehavior) activityBehaviorInstance).completed(execution);
} else {
throw new FlowableException("completed() can only be called on a " + SubProcessActivityBehavior.class.getName() + " instance for " + execution);
}
}
protected ActivityBehavior getActivityBehaviorInstance() {
Object delegateInstance = instantiateDelegate(className, fieldDeclarations);View on GitHub (pinned to d6d39ce1c6)
Solutions
- Make the delegate's ActivityBehavior implement (or extend AbstractBpmnActivityBehavior to gain) SubProcessActivityBehavior.
- Verify the class configured on the subprocess element is actually a subprocess behavior (e.g. extends SubProcessActivityBehavior).
- Ensure custom code only calls completing()/completed() for elements configured as subprocess behaviors.
- Restore the previous delegate class if a refactoring replaced a SubProcessActivityBehavior implementation.
Example fix
// before
public class MyBehavior implements ActivityBehavior { ... }
// after
public class MyBehavior extends AbstractBpmnActivityBehavior {
@Override public void completing(DelegateExecution execution, ExecutionContext subProcessInstance) { ... }
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!(behavior instanceof SubProcessActivityBehavior)) throw new IllegalStateException("Delegate must be a SubProcessActivityBehavior"); Type guard
boolean isSubProcessBehavior(ActivityBehavior b) { return b instanceof SubProcessActivityBehavior; } Try / catch
try {
runtimeService.startProcessInstanceByKey("proc");
} catch (FlowableException e) {
if (e.getMessage().contains("completing() can only be called")) { /* fix delegate class */ }
throw e;
} Prevention
- Extend AbstractBpmnActivityBehavior for subprocess delegates.
- Avoid calling internal completing()/completed() from application code.
- Keep subprocess delegate classes dedicated, not shared with plain tasks.
When it happens
Trigger: The inner activity of a subprocess/service-task-as-subprocess uses a ClassDelegate whose resolved ActivityBehavior does not implement SubProcessActivityBehavior, and the engine (or code) invokes completing(execution, subProcessInstance) when the subprocess instance finishes.
Common situations: Custom subprocess configuration pointing at a plain ActivityBehavior; a delegate class changed to no longer extend AbstractBpmnActivityBehavior/SubProcessActivityBehavior; engine internals or custom code calling completing() on a normal service task delegate.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- completed() can only be called on a SubProcessActivityBehavi
- signal() can only be called on a TriggerableActivityBehavior
- ${className} does not implement the ${CmmnTriggerableActivit
- ${className} does not implement the ${CmmnActivityBehavior.c
- CommandInvoker must be the last interceptor in the chain
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/04fe552f077e48fc.
Report an issue: GitHub.