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

  1. Make the delegate's ActivityBehavior implement (or extend AbstractBpmnActivityBehavior to gain) SubProcessActivityBehavior.
  2. Verify the class configured on the subprocess element is actually a subprocess behavior (e.g. extends SubProcessActivityBehavior).
  3. Ensure custom code only calls completing()/completed() for elements configured as subprocess behaviors.
  4. 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

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/04fe552f077e48fc. Report an issue: GitHub.