flowable/flowable-engine · error · FlowableException
Merge mode '' not found.
Error message
Merge mode '' not found.
What it means
ChangeDeploymentTenantIdCmd switches a deployment's tenant id and applies a merge mode (DEFAULT, BY_TIME, BY_DATE) selecting a DeploymentMergeStrategy. An unrecognized merge mode string reaches the switch's default branch and Flowable throws a generic FlowableException.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ChangeDeploymentTenantIdCmd.java:70
public ChangeDeploymentTenantIdCmd(String deploymentId, String newTenantId, MergeMode mergeMode) {
this.deploymentId = deploymentId;
this.newTenantId = newTenantId;
switch (mergeMode) {
case VERIFY:
deploymentMergeStrategy = new VerifyDeploymentMergeStrategy();
break;
case AS_NEW:
deploymentMergeStrategy = new AddAsNewDeploymentMergeStrategy();
break;
case AS_OLD:
deploymentMergeStrategy = new AddAsOldDeploymentMergeStrategy();
break;
case BY_DATE:
deploymentMergeStrategy = new MergeByDateDeploymentMergeStrategy();
break;
default:
throw new FlowableException("Merge mode '" + mergeMode + "' not found.");
}
}
public ChangeDeploymentTenantIdCmd(String deploymentId, String newTenantId, DeploymentMergeStrategy deploymentMergeStrategy) {
this.deploymentId = deploymentId;
this.newTenantId = newTenantId;
this.deploymentMergeStrategy = deploymentMergeStrategy;
}
@Override
public Void execute(CommandContext commandContext) {
if (deploymentId == null) {
throw new FlowableIllegalArgumentException("deploymentId is null");
}
// Update all entities
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
DeploymentEntity deployment = processEngineConfiguration.getDeploymentEntityManager().findById(deploymentId);View on GitHub (pinned to d6d39ce1c6)
Solutions
- Use one of the valid merge modes: DEFAULT, BY_TIME, or BY_DATE (constants on the cmd/related class).
- Fix the casing/spelling of the merge mode string.
- Inject a custom DeploymentMergeStrategy via the constructor overload instead of relying on a mode name.
Example fix
// before new ChangeDeploymentTenantIdCmd(deploymentId, tenantId, "BYDATE"); // after new ChangeDeploymentTenantIdCmd(deploymentId, tenantId, "BY_DATE");
Defensive patterns
Strategy: validation
Validate before calling
if (!"DEFAULT".equals(mergeMode) && !"BY_TIME".equals(mergeMode) && !"BY_DATE".equals(mergeMode)) {
throw new IllegalArgumentException("Unsupported merge mode: " + mergeMode);
} Try / catch
try {
repositoryService.changeDeploymentTenantId(deploymentId, tenantId);
} catch (FlowableException e) {
if (e.getMessage().contains("Merge mode")) {
// fall back to DEFAULT mode
}
} Prevention
- Use the mode constants, not hand-typed strings.
- Externalize merge mode from config with a whitelist validation at startup.
When it happens
Trigger: Passing an invalid mergeMode string when constructing ChangeDeploymentTenantIdCmd (e.g. typo or wrong casing) via the repositoryService deployment tenant API.
Common situations: Hardcoded mode constants changed or misspelled; configuration value mapped from an external config file with an unexpected value; upgrading Flowable and using a mode name that no longer exists.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Could not find deployment with id <deploymentId>
- No event definition found for event key ${sendEventServiceTa
- Could not find deployment with id
- No channel definition found for key '' for parent deployment
- No event definition found for key '${eventDefinitionKey} for
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/6958ab45790bdaa9.
Report an issue: GitHub.