flowable/flowable-engine · error · FlowableException

The new process definition

Error message

The new process definition (key = '${newProcessDefinition.getKey()}') does not contain the current activity (id = '${execution.getActivityId()}') of the process instance (id = '${processInstanceId}').

What it means

Before switching versions, the command checks that the new process definition version contains the activity the execution is currently sitting on. If the activity id does not resolve in the new BPMN model (including subprocess scopes), it throws FlowableException, because the execution could not continue after the switch.

Solutions

  1. Keep activity ids stable across definition versions when redeploying
  2. Move the instance off the missing activity (complete/signal it) before migrating, or migrate when it sits at a stable wait state present in both versions
  3. Add the missing activity (with the same id) to the new definition version and redeploy
  4. Use a migration tool (Flowable migration/ProcessInstanceMigration) that maps activity ids explicitly

Example fix

// before
// new version renamed userTask id 'review' to 'managerReview' then migrated
new SetProcessDefinitionVersionCmd(piId, 5);
// after
org.flowable.bpmn.model.Process p = ProcessDefinitionUtil.getProcess(newDefId);
if (p.getFlowElement(currentActivityId, true) != null) {
    new SetProcessDefinitionVersionCmd(piId, 5);
}
Defensive patterns

Strategy: try-catch

Validate before calling

org.flowable.bpmn.model.Process p = ProcessDefinitionUtil.getProcess(newDef.getId());
boolean compatible = execution.getActivityId() == null || p.getFlowElement(execution.getActivityId(), true) != null;

Try / catch

try { cmd.execute(ctx); } catch (FlowableException e) { if (e.getMessage().contains("does not contain the current activity")) { /* defer migration or remap activity */ } }

Prevention

When it happens

Trigger: Migrating a running instance whose current activity was added/renamed/removed in the new definition version, so process.getFlowElement(activityId, true) returns null.

Common situations: Redeploying a refactored BPMN where activity ids changed; instances parked at a boundary/subprocess activity deleted in the newer version; uncontrolled model drift between versions.

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/1caa6854a3eda382. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SetProcessDefinitionVersionCmd.java:120

        validateAndSwitchVersionOfExecution(commandContext, processInstance, newProcessDefinition);

        // switch the historic process instance to the new process definition version
        CommandContextUtil.getHistoryManager(commandContext).recordProcessDefinitionChange(processInstanceId, newProcessDefinition.getId());

        // switch all sub-executions of the process instance to the new process definition version
        Collection<ExecutionEntity> childExecutions = executionManager.findChildExecutionsByProcessInstanceId(processInstanceId);
        for (ExecutionEntity executionEntity : childExecutions) {
            validateAndSwitchVersionOfExecution(commandContext, executionEntity, newProcessDefinition);
        }

        return null;
    }

    protected void validateAndSwitchVersionOfExecution(CommandContext commandContext, ExecutionEntity execution, ProcessDefinition newProcessDefinition) {
        // check that the new process definition version contains the current activity
        org.flowable.bpmn.model.Process process = ProcessDefinitionUtil.getProcess(newProcessDefinition.getId());
        if (execution.getActivityId() != null && process.getFlowElement(execution.getActivityId(), true) == null) {
            throw new FlowableException("The new process definition " + "(key = '" + newProcessDefinition.getKey() + "') " + "does not contain the current activity " + "(id = '"
                    + execution.getActivityId() + "') " + "of the process instance " + "(id = '" + processInstanceId + "').");
        }

        // switch the process instance to the new process definition version
        execution.setProcessDefinitionId(newProcessDefinition.getId());
        execution.setProcessDefinitionName(newProcessDefinition.getName());
        execution.setProcessDefinitionKey(newProcessDefinition.getKey());

        // and change possible existing tasks (as the process definition id is stored there too)
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        List<TaskEntity> tasks = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().findTasksByExecutionId(execution.getId());
        Clock clock = processEngineConfiguration.getClock();
        for (TaskEntity taskEntity : tasks) {
            taskEntity.setProcessDefinitionId(newProcessDefinition.getId());
            processEngineConfiguration.getActivityInstanceEntityManager().recordTaskInfoChange(taskEntity, clock.getCurrentTime());
        }
    }

View on GitHub (pinned to d6d39ce1c6)