flowable/flowable-engine · error · FlowableException

Call activity '" + executionActivityId + "' does not exist…

Error message

Call activity '" + executionActivityId + "' does not exist in the new model. It must be mapped explicitly for migration (or all its child activities)

What it means

Thrown during auto-mapping when a call activity with running (unmapped) child instances has no explicit mapping and its activity id does not exist in the target process model. Migration of call activities with unmapped children requires the call activity itself to exist unchanged in the new model, otherwise instance state would be lost. The developer must map it explicitly.

Solutions

  1. Add an explicit activity mapping for the call activity in the migration document: .addActivityMapping(oldId, newId)
  2. Map all running child activities of the call activity explicitly so auto-mapping is not needed
  3. Restore or keep the call activity id unchanged in the target model
  4. Migrate the child process instances separately or terminate them before migrating

Example fix

// before
runtimeService.createProcessInstanceMigrationBuilder()
    .migrateToProcessDefinition(newDefId) // callActivity 'callTask1' removed in new model
    .migrate(instanceId);
// after
runtimeService.createProcessInstanceMigrationBuilder()
    .migrateToProcessDefinition(newDefId)
    .addActivityMapping("callTask1", "callTask2") // explicit mapping
    .migrate(instanceId);
Defensive patterns

Strategy: validation

Validate before calling

ProcessDefinition newDef = repositoryService.getProcessDefinition(targetDefId);
BpmnModel newModel = repositoryService.getBpmnModel(newDef.getId());
if (newModel.getFlowElement("callTask1") == null && runningChildrenUnmapped) {
    // add explicit mapping for callTask1 before migrating
}

Try / catch

try {
    migrationBuilder.migrate(instanceId);
} catch (FlowableException e) {
    if (e.getMessage().contains("Call activity") && e.getMessage().contains("does not exist in the new model")) {
        // rebuild document with explicit call activity mapping
    }
}

Prevention

When it happens

Trigger: Migrating a process instance whose current execution tree contains a call activity with running child process instances, no activity mapping covers the call activity (or all its children), and the target model has no flow element with that id.

Common situations: The new model renamed or removed the call activity; a process refactor deleted the sub-process invocation; the migration document omitted mappings for the call activity's children.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationManagerImpl.java:694

                if (subProcessActivityMappingsByCallActivityIdAndFromActivityId.containsKey(executionActivityId)) {
                    Set<String> mappedSubProcessActivityIds = subProcessActivityMappingsByCallActivityIdAndFromActivityId.get(executionActivityId).keySet();
                    List<ExecutionEntity> callActivityExecutions = filteredExecutionsByActivityId.get(executionActivityId).stream().filter(ExecutionEntity::isActive).collect(Collectors.toList());
                    for (ExecutionEntity callActivityExecution : callActivityExecutions) { //parallel MultiInstance call activities
                        List<ExecutionEntity> subProcessChildExecutions = executionEntityManager.findChildExecutionsByProcessInstanceId(callActivityExecution.getSubProcessInstance().getId());
                        Set<String> childSubProcessExecutionActivityIds = subProcessChildExecutions.stream().map(Execution::getActivityId).collect(Collectors.toSet());
                        childSubProcessExecutionActivityIds.removeAll(mappedSubProcessActivityIds);
                        if (!childSubProcessExecutionActivityIds.isEmpty()) {
                            runningChildrenNotFullyMapped = true;
                            break;
                        }
                    }
                }

                if (!subProcessActivityMappingsByCallActivityIdAndFromActivityId.containsKey(executionActivityId) || runningChildrenNotFullyMapped) {
                    //If there are running child activities not mapped, the call activity must be equally valid in the new model, the activityId in the new model must refer also to a callActivity with matching callElement
                    FlowElement newModelFlowElement = newModel.getFlowElement(executionActivityId);
                    if (newModelFlowElement == null) {
                        throw new FlowableException("Call activity '" + executionActivityId + "' does not exist in the new model. It must be mapped explicitly for migration (or all its child activities)");
                    }
                    if (newModelFlowElement instanceof CallActivity) {
                        if (!referToSameCalledElement((CallActivity) currentModelFlowElement, (CallActivity) newModelFlowElement)) {
                            throw new FlowableException("Call activity '" + executionActivityId + "' has a different called element in the new model. It must be mapped explicitly for migration (or all its child activities)");
                        }
                        if (((CallActivity) currentModelFlowElement).hasMultiInstanceLoopCharacteristics() ^ ((CallActivity) newModelFlowElement).hasMultiInstanceLoopCharacteristics()) {
                            throw new FlowableException("Call activity '" + executionActivityId + "' loop characteristics differs in new model. It must be mapped explicitly for migration (or all its child activities)");
                        }
                    } else {
                        throw new FlowableException("Call activity '" + executionActivityId + "' is not a Call Activity in the new model. It must be mapped explicitly for migration (or all its child activities)");
                    }
                }
            }

            String flowElementMultiInstanceParentId = getFlowElementMultiInstanceParentId(currentModelFlowElement);
            if (flowElementMultiInstanceParentId != null && mappedFromActivities.contains(flowElementMultiInstanceParentId)) {
                // Add the parent MI execution activity Id to be explicitly mapped...
                if (!executionActivityIdsToMapExplicitly.contains(flowElementMultiInstanceParentId)) {

View on GitHub (pinned to d6d39ce1c6)