flowable/flowable-engine · error · FlowableException

Tenant mismatch between Process Instance ('" + processInstan

Error message

Tenant mismatch between Process Instance ('" + processInstanceExecution.getTenantId() + "') and Process Definition ('" + procDefTenantId + "') to migrate to

What it means

FlowableException thrown when the tenant id of the running process instance does not match, and is not a permitted default, the tenant id of the target process definition during instance migration. Migration is tenant-checked because tenant is part of process definition isolation. Thrown by isSameOrDefaultTenant check in prepareChangeStateBuilders.

Source

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

        Object delegate = DelegateExpressionUtil.resolveDelegateExpression(expression, (VariableContainer) processInstance, Collections.emptyList());
        if (delegate instanceof ActivityBehavior) {
            CommandContextUtil.getProcessEngineConfiguration(commandContext).getDelegateInterceptor().handleInvocation(new ActivityBehaviorInvocation((ActivityBehavior) delegate, (ExecutionEntityImpl) processInstance));
        } else if (delegate instanceof JavaDelegate) {
            CommandContextUtil.getProcessEngineConfiguration(commandContext).getDelegateInterceptor().handleInvocation(new JavaDelegateInvocation((JavaDelegate) delegate, (ExecutionEntityImpl) processInstance));
        } else {
            throw new FlowableIllegalArgumentException("Delegate expression " + expression + " did neither resolve to an implementation of " + ActivityBehavior.class + " nor " + JavaDelegate.class);
        }
    }

    protected List<ChangeActivityStateBuilderImpl> prepareChangeStateBuilders(ExecutionEntity processInstanceExecution, ProcessDefinition procDefToMigrateTo, ProcessInstanceMigrationDocument document, CommandContext commandContext) {
        ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);

        // Check processDefinition tenant
        String procDefTenantId = procDefToMigrateTo.getTenantId();
        if (!isSameOrDefaultTenant(processInstanceExecution.getTenantId(), procDefToMigrateTo.getKey(), 
                procDefTenantId, CommandContextUtil.getProcessEngineConfiguration(commandContext))) {
            
            throw new FlowableException("Tenant mismatch between Process Instance ('" + processInstanceExecution.getTenantId() + "') and Process Definition ('" + procDefTenantId + "') to migrate to");
        }

        List<ChangeActivityStateBuilderImpl> changeActivityStateBuilders = new ArrayList<>();
        ChangeActivityStateBuilderImpl mainProcessChangeActivityStateBuilder = new ChangeActivityStateBuilderImpl();
        mainProcessChangeActivityStateBuilder.processInstanceId(processInstanceExecution.getId());
        changeActivityStateBuilders.add(mainProcessChangeActivityStateBuilder);

        // Current executions to migrate...
        Map<String, List<ExecutionEntity>> filteredExecutionsByActivityId = executionEntityManager.findChildExecutionsByProcessInstanceId(processInstanceExecution.getId())
            .stream()
            .filter(executionEntity -> executionEntity.getCurrentActivityId() != null)
            .filter(executionEntity -> !(executionEntity.getCurrentFlowElement() instanceof SubProcess))
            .filter(executionEntity -> !(executionEntity.getCurrentFlowElement() instanceof BoundaryEvent))
            .collect(Collectors.groupingBy(ExecutionEntity::getCurrentActivityId));

        LOGGER.debug("Preparing ActivityChangeState builder for '{}' distinct activities", filteredExecutionsByActivityId.size());

        HashMap<String, ActivityMigrationMapping> mainProcessActivityMappingByFromActivityId = new HashMap<>();

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Migrate to a definition deployed with the same tenant id as the process instance
  2. Redeploy the target process definition with the instance's tenant id
  3. If instance tenant is the default (empty), ensure a definition for the given key exists for that default tenant
  4. Use the tenant-aware migration API (migrateToProcessDefinition with tenant validation) and verify tenants first

Example fix

// before
repositoryService.createDeployment().addClasspathResource("orderProcess.bpmn20.xml").deploy(); // no tenant
// after
repositoryService.createDeployment().addClasspathResource("orderProcess.bpmn20.xml").tenantId("tenant-A").deploy();
Defensive patterns

Strategy: validation

Validate before calling

ProcessDefinition procDef = repositoryService.getProcessDefinition(targetDefId);
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
if (!procDef.getTenantId().equals(pi.getTenantId())) {
    throw new IllegalStateException("Tenant mismatch: " + pi.getTenantId() + " vs " + procDef.getTenantId());
}

Type guard

boolean sameTenant(String instanceTenant, String defTenant) {
    return instanceTenant == null ? defTenant.isEmpty() : instanceTenant.equals(defTenant);
}

Try / catch

try {
    migrationBuilder.migrate(instanceId);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Tenant mismatch")) {
        // deploy/redeploy target definition under the instance tenant
    }
}

Prevention

When it happens

Trigger: Calling ProcessInstanceMigrationBuilder.migrateToProcessDefinition(defId) where the target definition's tenant differs from the instance's tenant and no tenant-validated definition exists.

Common situations: Multi-tenant deployments where the target definition was deployed under a different tenant; deploying a new version of a definition without setting the same tenant; accidentally targeting a definition from tenant A for a tenant B instance.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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