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

This constructor of HistoricCaseInstanceMigrationCmd migrates ALL historic case instances of a given case definition by id. It validates that caseDefinitionId is non-null, throwing FlowableException immediately otherwise, since a batch-by-definition migration without the target definition id cannot proceed.

Source

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

            CmmnEngineConfiguration cmmnEngineConfiguration) {
        
        if (caseInstanceId == null) {
            throw new FlowableException("Must specify a historic case instance id to migrate");
        }
        if (historicCaseInstanceMigrationDocument == null) {
            throw new FlowableException("Must specify a historic case instance migration document to migrate");
        }
        
        this.caseInstanceId = caseInstanceId;
        this.historicCaseInstanceMigrationDocument = historicCaseInstanceMigrationDocument;
        this.cmmnEngineConfiguration = cmmnEngineConfiguration;
    }

    public HistoricCaseInstanceMigrationCmd(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 HistoricCaseInstanceMigrationCmd(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. Resolve the definition id first: cmmnRepositoryService.createCaseDefinitionQuery().caseDefinitionKey(key).latestVersion().singleResult().getId().
  2. If you only have the key, use a key/version/tenant-based migration builder variant instead of this id-based command.
  3. Null-check the id before constructing the command.

Example fix

// before
String defId = caseDefinitionQuery.singleResult() != null
    ? caseDefinitionQuery.singleResult().getId() : null; // null when not found
new HistoricCaseInstanceMigrationCmd(doc, defId, cfg);

// after
CaseDefinition def = caseDefinitionQuery.singleResult();
if (def == null) throw new IllegalStateException("Deploy the case definition first");
new HistoricCaseInstanceMigrationCmd(doc, def.getId(), cfg);
Defensive patterns

Strategy: validation

Validate before calling

if (caseDefinitionId == null || caseDefinitionId.isBlank())
    throw new IllegalArgumentException("caseDefinitionId required to migrate historic instances of a definition");
CaseDefinition def = cmmnRepositoryService.createCaseDefinitionQuery()
    .caseDefinitionId(caseDefinitionId).singleResult();
if (def == null) throw new IllegalArgumentException("No deployed case definition with id " + caseDefinitionId);

Type guard

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

Try / catch

try {
    execute(new HistoricCaseInstanceMigrationCmd(doc, caseDefinitionId, cfg));
} catch (FlowableException e) {
    if (e.getMessage().contains("Must specify a case definition id")) {
        throw new ConfigurationException("Resolve the deployed definition id first", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling new HistoricCaseInstanceMigrationCmd(migrationDocument, null, cmmnEngineConfiguration) — e.g. definition id from an unpopulated lookup, wrong constructor overload chosen (id passed into the single-instance position or vice versa), or a null from a properties/CDI/Spring injection point.

Common situations: Definition deployed under a different key so createCaseDefinitionQuery() returned null and getId() was never called; copy-paste refactor dropped the id argument; confusing id vs key (this overload needs the database id, not the model key).

Related errors


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