flowable/flowable-engine · error · FlowableException

Cannot migrate historic case instances, not enough informati

Error message

Cannot migrate historic case instances, not enough information

What it means

HistoricCaseInstanceMigrationBatchCmd.execute() dispatches to the migration manager either by caseDefinitionId or by (key, version, tenantId). If none of those identifying fields are set, there is no way to select historic case instances, so execute() throws FlowableException('Cannot migrate historic case instances, not enough information'). This can only happen when an instance was created bypassing the validating constructors (e.g. deserialization or a default constructor path).

Source

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

        }
        this.caseDefinitionKey = caseDefinitionKey;
        this.caseDefinitionVersion = caseDefinitionVersion;
        this.caseDefinitionTenantId = caseDefinitionTenantId;
        this.historicCaseInstanceMigrationDocument = historicCaseInstanceMigrationDocument;
        this.cmmnEngineConfiguration = cmmnEngineConfiguration;
    }

    @Override
    public Batch execute(CommandContext commandContext) {
        CaseInstanceMigrationManager migrationManager = cmmnEngineConfiguration.getCaseInstanceMigrationManager();

        if (caseDefinitionId != null) {
            return migrationManager.batchMigrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionId, historicCaseInstanceMigrationDocument, commandContext);
        } else if (caseDefinitionKey != null && caseDefinitionVersion >= 0) {
            return migrationManager.batchMigrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionKey, caseDefinitionVersion, caseDefinitionTenantId, 
                    historicCaseInstanceMigrationDocument, commandContext);
        } else {
            throw new FlowableException("Cannot migrate historic case instances, not enough information");
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Set caseDefinitionId (or the key/version/tenant triple with version >= 0) via the proper public constructor before executing the command.
  2. If using key-based migration, ensure caseDefinitionVersion is a real deployed version number (>= 0); do not pass -1 as a 'latest' sentinel.
  3. Avoid building this command reflectively or via a default-constructed instance; use HistoricCaseInstanceMigrationBuilder on the CmmnEngineConfiguration which populates fields correctly.

Example fix

// before
HistoricCaseInstanceMigrationBatchCmd cmd = new HistoricCaseInstanceMigrationBatchCmd();
cmd.setMigrationDocument(doc); // no definition info set -> execute() throws

// after
HistoricCaseInstanceMigrationBatchCmd cmd = new HistoricCaseInstanceMigrationBatchCmd(
    "myCase", 2, "acme-tenant", doc, cmmnEngineConfiguration); // fully identified
Defensive patterns

Strategy: validation

Validate before calling

boolean canExecute = caseDefinitionId != null
    || (caseDefinitionKey != null && caseDefinitionVersion >= 0 && tenantId != null);
if (!canExecute)
    throw new IllegalArgumentException("Provide definition id or (key, version >= 0, tenant) before executing batch migration");

Type guard

boolean hasMigrationTarget(String id, String key, int version) {
    return id != null || (key != null && version >= 0);
}

Try / catch

try {
    command.execute(commandContext);
} catch (FlowableException e) {
    if (e.getMessage().contains("not enough information")) {
        throw new ConfigurationException("Command built without definition id or key/version/tenant; use the public constructors", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing a HistoricCaseInstanceMigrationBatchCmd where caseDefinitionId == null AND (caseDefinitionKey == null OR caseDefinitionVersion < 0) — e.g. the object was built through a no-arg/reflective path or setters were never called; or caseDefinitionVersion left at its default (e.g. -1/0 sentinel below the >= 0 check).

Common situations: Constructing the command via reflection/serialization frameworks that skip constructor validation; copying a command object partially initialized; passing version 0 or -1 as 'latest' instead of a positive version number.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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