flowable/flowable-engine · error · FlowableException

No multi instance behavior found for ${execution}

Error message

No multi instance behavior found for ${execution}

What it means

Thrown by DeleteMultiInstanceExecutionCmd.execute() when the activity element for the target execution has loop characteristics but its behavior is not a MultiInstanceActivityBehavior. The command only knows how to delete executions that belong to a genuine multi-instance activity. This guards against deleting executions of activities that merely resemble multi-instance constructs.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/DeleteMultiInstanceExecutionCmd.java:65

        this.executionId = executionId;
        this.executionIsCompleted = executionIsCompleted;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
        ExecutionEntity execution = executionEntityManager.findById(executionId);
        
        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(execution.getProcessDefinitionId());
        Activity miActivityElement = (Activity) bpmnModel.getFlowElement(execution.getActivityId());
        MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = miActivityElement.getLoopCharacteristics();
        
        if (miActivityElement.getLoopCharacteristics() == null) {
            throw new FlowableException("No multi instance execution found for " + execution);
        }
        
        if (!(miActivityElement.getBehavior() instanceof MultiInstanceActivityBehavior)) {
            throw new FlowableException("No multi instance behavior found for " + execution);
        }
        
        if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, execution.getProcessDefinitionId())) {
            throw new FlowableException("Flowable 5 process definitions are not supported for " + execution);
        }
        
        ExecutionEntity miExecution = getMultiInstanceRootExecution(execution);
        executionEntityManager.deleteChildExecutions(execution, "Delete MI execution", false);
        executionEntityManager.deleteExecutionAndRelatedData(execution, "Delete MI execution", false);
        
        int loopCounter = 0;
        if (multiInstanceLoopCharacteristics.isSequential()) {
            SequentialMultiInstanceBehavior miBehavior = (SequentialMultiInstanceBehavior) miActivityElement.getBehavior();
            loopCounter = miBehavior.getLoopVariable(execution, miBehavior.getCollectionElementIndexVariable());
        }
        
        if (executionIsCompleted) {
            VariableInstance nrOfCompletedInstancesVariable = miExecution.getVariableInstance(NUMBER_OF_COMPLETED_INSTANCES);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the execution you pass actually belongs to a multi-instance user task or subprocess (check ACT_GE_BYTEARRAY/BPMN XML for loopCharacteristics on the activity).
  2. Inspect the deployed BPMN model: the activity element must have an embedded MultiInstanceActivityBehavior; redeploy a correct process definition if behavior was customized.
  3. Do not call this command on child/inner MI executions; use the multi-instance root execution id.
  4. If behavior was overridden programmatically, ensure it extends MultiInstanceActivityBehavior.

Example fix

// before
runtimeService.deleteMultiInstanceExecutionForExecution(childExecutionId);
// after
Execution pi = runtimeService.createExecutionQuery().executionId(childExecutionId).singleResult();
Execution miRoot = runtimeService.createProcessInstanceQuery()
    .processInstanceId(pi.getProcessInstanceId()).singleResult(); // verify activity is MI first
runtimeService.deleteMultiInstanceExecutionForExecution(miRootExecutionId);
Defensive patterns

Strategy: validation

Validate before calling

boolean isMultiInstance(RuntimeService rs, String executionId) {
    Execution e = rs.createExecutionQuery().executionId(executionId).singleResult();
    return e != null && e.getActivityId() != null; // confirm via model inspection
}

Type guard

if (execution == null || execution.getActivityId() == null) return false;

Prevention

When it happens

Trigger: Calling runtimeService.deleteMultiInstanceExecutionForExecution (or the underlying command) with an execution whose activity's behavior is not a MultiInstanceActivityBehavior, even though loopCharacteristics is non-null (that check passes at line 62).

Common situations: Custom or overridden activity behavior replaced the MI behavior; a parser/transformer bug left the behavior unassigned; calling the command on the inner (concurrent) child execution of an MI activity rather than a valid MI execution in a modified engine build.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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