flowable/flowable-engine · error · FlowableException

Must specify a case definition id to migrate

Error message

Must specify a case definition id to migrate

What it means

HistoricCaseInstanceMigrationBatchCmd's constructor requires a target caseDefinitionId for batch-migrating historic case instances. When it is null, the command immediately throws FlowableException rather than failing later during execution. This fail-fast check guarantees the migration manager always has an unambiguous case definition to operate on.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/HistoricCaseInstanceMigrationBatchCmd.java:38

import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;

public class HistoricCaseInstanceMigrationBatchCmd implements Command<Batch> {

    protected CmmnEngineConfiguration cmmnEngineConfiguration;
    
    protected String caseDefinitionId;
    protected String caseDefinitionKey;
    protected int caseDefinitionVersion;
    protected String caseDefinitionTenantId;
    protected HistoricCaseInstanceMigrationDocument historicCaseInstanceMigrationDocument;

    public HistoricCaseInstanceMigrationBatchCmd(HistoricCaseInstanceMigrationDocument historicCaseInstanceMigrationDocument, String caseDefinitionId,
            CmmnEngineConfiguration cmmnEngineConfiguration) {
        
        if (caseDefinitionId == null) {
            throw new FlowableException("Must specify a case definition id to migrate");
        }
        if (historicCaseInstanceMigrationDocument == null) {
            throw new FlowableException("Must specify a historic case instance migration document to migrate");
        }
        this.caseDefinitionId = caseDefinitionId;
        this.historicCaseInstanceMigrationDocument = historicCaseInstanceMigrationDocument;
        this.cmmnEngineConfiguration = cmmnEngineConfiguration;
    }

    public HistoricCaseInstanceMigrationBatchCmd(String caseDefinitionKey, int caseDefinitionVersion, String caseDefinitionTenantId, 
            HistoricCaseInstanceMigrationDocument historicCaseInstanceMigrationDocument, CmmnEngineConfiguration cmmnEngineConfiguration) {
        
        if (caseDefinitionKey == null) {
            throw new FlowableException("Must specify a case definition id to migrate");
        }
        if (caseDefinitionTenantId == null) {
            throw new FlowableException("Must specify a case definition tenant id to migrate");
        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a valid, deployed case definition id (from CmmnRepositoryService.createCaseDefinitionQuery().caseDefinitionKey(...).singleResult().getId()) into the constructor.
  2. If you only know key/version/tenant, use the HistoricCaseInstanceMigrationBatchCmd(caseDefinitionKey, version, tenantId, document, config) constructor instead.
  3. Null-check or assert the definition id before constructing the command so the failure surfaces in your code with a clear message.

Example fix

// before
caseEngineConfig.getCmmnEngineConfiguration().getCommandExecutor().execute(
    new HistoricCaseInstanceMigrationBatchCmd(doc, caseDefId, cfg)); // caseDefId == null

// after
CaseDefinition def = cmmnRepoService.createCaseDefinitionQuery()
    .caseDefinitionKey("myCase").latestVersion().singleResult();
if (def == null) throw new IllegalStateException("Case definition not deployed");
new HistoricCaseInstanceMigrationBatchCmd(doc, def.getId(), cfg);
Defensive patterns

Strategy: validation

Validate before calling

if (caseDefinitionId == null || caseDefinitionId.isBlank())
    throw new IllegalArgumentException("caseDefinitionId required for historic batch migration");
// optionally verify deployment:
CaseDefinition def = cmmnRepositoryService.createCaseDefinitionQuery()
    .caseDefinitionId(caseDefinitionId).singleResult();
if (def == null) throw new IllegalArgumentException("Unknown caseDefinitionId: " + caseDefinitionId);

Type guard

boolean isValidDefinitionId(String id) { return id != null && !id.isBlank(); }

Try / catch

try {
    historyService.createHistoricCaseInstanceMigrationBuilder()...executeBatch();
} catch (FlowableException e) {
    if (e.getMessage().contains("Must specify a case definition id")) {
        throw new ConfigurationException("Resolve the target case definition id before migrating", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling new HistoricCaseInstanceMigrationBatchCmd(document, cmmnEngineConfiguration) variant path where caseDefinitionId is null — e.g. building the command programmatically with a variable that was never populated, or a migration builder API that left the definition id unset.

Common situations: Passing the result of caseDefinition.getId() from a lookup that returned null (definition not deployed under expected key/tenant); copy-pasting a single-instance migration call into the batch constructor; Spring bean wiring where the id property is missing.

Related errors


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