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

  1. Use one of the valid merge modes: DEFAULT, BY_TIME, or BY_DATE (constants on the cmd/related class).
  2. Fix the casing/spelling of the merge mode string.
  3. 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

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


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