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
- Migrate to a definition deployed with the same tenant id as the process instance
- Redeploy the target process definition with the instance's tenant id
- If instance tenant is the default (empty), ensure a definition for the given key exists for that default tenant
- 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
- Set tenantId on every deployment in multi-tenant apps
- Query candidate definitions with tenantId filters before migrating
- Add tenant checks to CI tests for migration scenarios
- Keep tenant conventions (default vs explicit) documented and enforced
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
- Tenant mismatch between Historic Case Instance ('${historicC
- No process definition found for key '${processDefinitionKey}
- No channel definition found for key '' for tenant identifier
- Provided tenant id is null
- app definition tenantId is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/5cbd6df79843bfa4.
Report an issue: GitHub.