flowable/flowable-engine · error · FlowableException

Multiple multi instance executions found for activity id

Error message

Multiple multi instance executions found for activity id 

What it means

Thrown by AddMultiInstanceExecutionCmd's recursive searchForMultiInstanceActivity when more than one child execution matches the given activityId and is flagged as a multi-instance root. The dynamic-addition API requires exactly one MI root execution per activity id; finding two means the execution tree is ambiguous or corrupted, so the engine refuses to guess which MI root to add the new instance to.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/AddMultiInstanceExecutionCmd.java:97

        if (!multiInstanceLoopCharacteristics.isSequential()) {
            miExecution.setActive(true);
            miExecution.setScope(false);
            
            childExecution.setCurrentFlowElement(miActivityElement);
            CommandContextUtil.getAgenda().planContinueMultiInstanceOperation(childExecution, miExecution, currentNumberOfInstances);
        }
        
        return childExecution;
    }
    
    protected ExecutionEntity searchForMultiInstanceActivity(String activityId, String parentExecutionId, ExecutionEntityManager executionEntityManager) {
        List<ExecutionEntity> childExecutions = executionEntityManager.findChildExecutionsByParentExecutionId(parentExecutionId);
        
        ExecutionEntity miExecution = null;
        for (ExecutionEntity childExecution : childExecutions) {
            if (activityId.equals(childExecution.getActivityId()) && childExecution.isMultiInstanceRoot()) {
                if (miExecution != null) {
                    throw new FlowableException("Multiple multi instance executions found for activity id " + activityId + " in " + childExecution);
                }
                miExecution = childExecution;
            }
            
            ExecutionEntity childMiExecution = searchForMultiInstanceActivity(activityId, childExecution.getId(), executionEntityManager);
            if (childMiExecution != null) {
                if (miExecution != null) {
                    throw new FlowableException("Multiple multi instance executions found for activity id " + activityId + " in " + childExecution);
                }
                miExecution = childMiExecution;
            }
        }
        
        return miExecution;
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Inspect ACT_RU_EXECUTION for all rows with the given activity id and MULTI_INSTANCE_ROOT_OF_=1 in the process instance; delete or correct the stale duplicate (only with runtime data expertise and after backing up).
  2. Reproduce and fix the process definition: if nested MI activities share an activity id (or the activityId passed to addMultiInstanceExecution matches both an inner and outer MI), give each MI activity a unique id.
  3. If triggered by cancellation logic, ensure the MI root and its children are fully removed on termination — upgrade Flowable to a version fixing MI deletion on terminate/boundary events.
  4. As a workaround, delete the affected process instance and restart the process from a clean state, migrating business data manually.
  5. Enable debug logging for org.flowable.engine.impl.cmd to trace which executions the search visits before throwing.

Example fix

// before (ambiguous call)
runtimeService.addMultiInstanceExecution("approveTask", processInstanceId, vars);
// after (use the exact execution id of the MI root if available)
Execution miRoot = runtimeService.createExecutionQuery()
    .processInstanceId(processInstanceId)
    .activityId("approveTask")
    .onlyChildExecutions()
    .singleResult();
if (miRoot != null) {
    runtimeService.addMultiInstanceExecution("approveTask", miRoot.getId(), vars);
}
Defensive patterns

Strategy: validation

Validate before calling

long count = runtimeService.createExecutionQuery()
    .processInstanceId(processInstanceId)
    .activityId(activityId)
    .count();
if (count != 1) {
    throw new IllegalStateException("Expected exactly 1 execution for " + activityId + ", found " + count);
}

Type guard

boolean hasSingleMiRoot(List<Execution> execs, String activityId) {
    return execs.stream().filter(e -> activityId.equals(e.getActivityId())).count() == 1;
}

Try / catch

try {
    runtimeService.addMultiInstanceExecution(activityId, processInstanceId, vars);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Multiple multi instance executions found")) {
        // repair or restart the process instance
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling runtimeService.addMultiInstanceExecution(activityId, processInstanceId, executionVariables) when the process contains (or has wrongly persisted) two multi-instance-root executions with the same activity id — e.g. a duplicate MI root left behind by an incomplete termination/compensation, or nested MI inside MI where both parent-scope recursion and child recursion each match the same activity id.

Common situations: Historic/dirty runtime data after a failed MI loop cancellation (e.g. terminate end event or boundary event interrupted the MI root deletion); process model changes redeployed over running instances where activity ids collide across nested scopes; manual manipulation or migration of ACT_RU_EXECUTION rows.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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