flowable/flowable-engine · error · FlowableException
CaseMigrationService cannot be null, Obtain your builder…
Error message
CaseMigrationService cannot be null, Obtain your builder instance from the CaseMigrationService to access this feature
What it means
HistoricCaseInstanceMigrationBuilderImpl relies on a reference to the CaseMigrationService that created it. If the builder was constructed directly (not via CaseMigrationService.createHistoricCaseInstanceMigrationBuilder()), that reference is null and any migrate/batch operation fails with this FlowableException.
Solutions
- Obtain the builder via cmmnEngineConfiguration.getCaseMigrationService().createHistoricCaseInstanceMigrationBuilder() (or the CmmnEngine/public API equivalent).
- Inject/set the CmmnMigrationService into the builder if you must construct it manually.
- Refactor to use the CmmnRuntimeService/CmmnManagementService migration API entry points instead of instantiating internal classes.
Example fix
// before
HistoricCaseInstanceMigrationBuilderImpl b = new HistoricCaseInstanceMigrationBuilderImpl();
b.migrateToCaseDefinition("orderCase").migrate();
// after
HistoricCaseInstanceMigrationBuilder b = cmmnEngineConfiguration.getCaseMigrationService()
.createHistoricCaseInstanceMigrationBuilder();
b.migrateToCaseDefinition("orderCase").migrate(); Defensive patterns
Strategy: type-guard
Validate before calling
if (builder == null || ((HistoricCaseInstanceMigrationBuilderImpl) builder).getCmmnMigrationServiceForTest() == null) {
throw new IllegalStateException("Builder must be created via CaseMigrationService");
} Type guard
if (migrationService == null) throw new IllegalStateException("Create the builder via CaseMigrationService.createHistoricCaseInstanceMigrationBuilder()"); Try / catch
try { builder.migrate(); } catch (FlowableException e) { if (e.getMessage().contains("CaseMigrationService cannot be null")) { /* rebuild via service factory */ } throw e; } Prevention
- Never instantiate migration builders with new; always use CaseMigrationService factory methods.
- In Spring configs, expose CaseMigrationService as a bean and inject it.
- Add constructor guards in wrappers around internal engine classes.
- Prefer the public CmmnRuntimeService/ManagementService migration APIs.
When it happens
Trigger: Instantiating HistoricCaseInstanceMigrationBuilderImpl with new (or via a non-standard factory) and then calling migrate(), migrateHistoricCaseInstances(...) or batchMigrateHistoricCaseInstances(...) without ever setting cmmnMigrationService.
Common situations: Manual bean construction/DI wiring that skips the service factory; copying builder creation code without injecting the migration service; unit tests constructing the builder directly.
Related errors
- Cannot find the case definition to migrate to, identified by
- Cannot find the case to migrate, with id
- Cannot find the historic case instance to migrate, with id
- Cannot migrate case(es), not enough information
- Cannot start case instance: no case instance builder…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/be831f1dedb9e2ea.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/migration/HistoricCaseInstanceMigrationBuilderImpl.java:96
@Override
public Batch batchMigrateHistoricCaseInstances(String caseDefinitionId) {
return getCmmnMigrationService().batchMigrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionId, getHistoricCaseInstanceMigrationDocument());
}
@Override
public void migrateHistoricCaseInstances(String caseDefinitionKey, int caseDefinitionVersion, String caseDefinitionTenantId) {
getCmmnMigrationService().migrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionKey, caseDefinitionVersion, caseDefinitionTenantId, getHistoricCaseInstanceMigrationDocument());
}
@Override
public Batch batchMigrateHistoricCaseInstances(String caseDefinitionKey, int caseDefinitionVersion, String caseDefinitionTenantId) {
return getCmmnMigrationService().batchMigrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionKey, caseDefinitionVersion, caseDefinitionTenantId, getHistoricCaseInstanceMigrationDocument());
}
protected CmmnMigrationService getCmmnMigrationService() {
if (cmmnMigrationService == null) {
throw new FlowableException("CaseMigrationService cannot be null, Obtain your builder instance from the CaseMigrationService to access this feature");
}
return cmmnMigrationService;
}
}
View on GitHub (pinned to d6d39ce1c6)