flowable/flowable-engine · error · FlowableException

Call activity '" + executionActivityId + "' has a different…

Error message

Call activity '" + executionActivityId + "' has a different called element in the new model. It must be mapped explicitly for migration (or all its child activities)

What it means

Thrown when a call activity with running unmapped child instances exists in both models with the same id, but the called element (the target process definition key) differs between old and new models. Such a change would redirect running children to a different subprocess definition, which Flowable refuses without an explicit mapping.

Solutions

  1. Add an explicit activity mapping for the call activity in the migration document
  2. Keep the calledElement unchanged in the target model version
  3. Terminate/complete running child process instances before migration, then map the activity
  4. If children should follow the new called element, plan a separate migration of the child instances and map explicitly

Example fix

// before
// new model: <callActivity id="callOrder" calledElement="orderV2"/> while old was orderV1, unmapped
// after
migrationBuilder.addActivityMapping("callOrder", "callOrder"); // explicit mapping allows the change
Defensive patterns

Strategy: validation

Validate before calling

CallActivity oldCa = (CallActivity) oldModel.getFlowElement("callTask1");
FlowElement newEl = newModel.getFlowElement("callTask1");
if (newEl instanceof CallActivity && !((CallActivity) newEl).getCalledElement().equals(oldCa.getCalledElement())) {
    // add explicit mapping or keep calledElement identical
}

Try / catch

try {
    migrationBuilder.migrate(instanceId);
} catch (FlowableException e) {
    if (e.getMessage().contains("has a different called element")) {
        // map the call activity explicitly or revert the calledElement change
    }
}

Prevention

When it happens

Trigger: Migrating instances of a parent process where a call activity's calledElement attribute was changed in the new model version and no explicit activity mapping exists for that call activity.

Common situations: Refactoring the subprocess out or pointing the call activity to a new subprocess key; copy-pasted definition versions where calledElement drifted; renaming the subprocess without mapping.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

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

                        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)) {
                    executionActivityIdsToMapExplicitly.add(flowElementMultiInstanceParentId);
                }
                // The root executions are the ones to migrate and are explicitly mapped
                List<ExecutionEntity> miRootExecutions = (List<ExecutionEntity>) executionEntityManager.findInactiveExecutionsByActivityIdAndProcessInstanceId(flowElementMultiInstanceParentId, processInstanceExecution.getId());

View on GitHub (pinned to d6d39ce1c6)