{"record":{"id":"323aff62422c2710","repo":"flowable/flowable-engine","slug":"must-specify-a-historic-case-instance-migration-do","errorCode":null,"errorMessage":"Must specify a historic case instance migration document to migrate","messagePattern":"Must specify a historic case instance migration document to migrate","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/HistoricCaseInstanceMigrationBatchCmd.java","lineNumber":41,"sourceCode":"\npublic class HistoricCaseInstanceMigrationBatchCmd implements Command<Batch> {\n\n    protected CmmnEngineConfiguration cmmnEngineConfiguration;\n    \n    protected String caseDefinitionId;\n    protected String caseDefinitionKey;\n    protected int caseDefinitionVersion;\n    protected String caseDefinitionTenantId;\n    protected HistoricCaseInstanceMigrationDocument historicCaseInstanceMigrationDocument;\n\n    public HistoricCaseInstanceMigrationBatchCmd(HistoricCaseInstanceMigrationDocument historicCaseInstanceMigrationDocument, String caseDefinitionId,\n            CmmnEngineConfiguration cmmnEngineConfiguration) {\n        \n        if (caseDefinitionId == null) {\n            throw new FlowableException(\"Must specify a case definition id to migrate\");\n        }\n        if (historicCaseInstanceMigrationDocument == null) {\n            throw new FlowableException(\"Must specify a historic case instance migration document to migrate\");\n        }\n        this.caseDefinitionId = caseDefinitionId;\n        this.historicCaseInstanceMigrationDocument = historicCaseInstanceMigrationDocument;\n        this.cmmnEngineConfiguration = cmmnEngineConfiguration;\n    }\n\n    public HistoricCaseInstanceMigrationBatchCmd(String caseDefinitionKey, int caseDefinitionVersion, String caseDefinitionTenantId, \n            HistoricCaseInstanceMigrationDocument historicCaseInstanceMigrationDocument, CmmnEngineConfiguration cmmnEngineConfiguration) {\n        \n        if (caseDefinitionKey == null) {\n            throw new FlowableException(\"Must specify a case definition id to migrate\");\n        }\n        if (caseDefinitionTenantId == null) {\n            throw new FlowableException(\"Must specify a case definition tenant id to migrate\");\n        }\n        if (historicCaseInstanceMigrationDocument == null) {\n            throw new FlowableException(\"Must specify a historic case instance migration document to migrate\");\n        }","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/HistoricCaseInstanceMigrationBatchCmd.java#L23-L59","documentation":"The batch migration command needs a HistoricCaseInstanceMigrationDocument describing how historic case instances (and their plan items) map to the new case definition. If that document is null the constructor throws immediately, because a migration without mapping instructions is meaningless and would fail in the migration manager anyway.","triggerScenarios":"Calling new HistoricCaseInstanceMigrationBatchCmd(caseDefinitionId, null, cmmnEngineConfiguration), e.g. forgetting to call HistoricCaseInstanceMigrationBuilder's mapping methods so createMigrationDocument()/the builder produced null, or passing an uninitialized field.","commonSituations":"Builder pattern misuse: creating the builder but never calling migrateCaseDefinitionTo(...)/map... methods before building; JSON migration document failed to parse and the variable stayed null; refactoring removed document construction.","solutions":["Build a migration document first via cmmnEngineConfiguration.getCaseInstanceMigrationManager() / HistoricCaseInstanceMigrationBuilder and pass its result.","If loading from a file, parse it with HistoricCaseInstanceMigrationDocument.fromJson(json) and check the return value is non-null before constructing the command.","Null-check the document before invoking the constructor."],"exampleFix":"// before\nHistoricCaseInstanceMigrationBatchCmd cmd =\n    new HistoricCaseInstanceMigrationBatchCmd(caseDefId, migrationDoc, cfg); // migrationDoc == null\n\n// after\nHistoricCaseInstanceMigrationDocument migrationDoc = HistoricCaseInstanceMigrationDocument.fromJson(jsonString);\nassert migrationDoc != null;\nHistoricCaseInstanceMigrationBatchCmd cmd =\n    new HistoricCaseInstanceMigrationBatchCmd(caseDefId, migrationDoc, cfg);","handlingStrategy":"validation","validationCode":"if (migrationDocument == null)\n    throw new IllegalArgumentException(\"Build HistoricCaseInstanceMigrationDocument before batch migration\");","typeGuard":"boolean isReadyForBatch(HistoricCaseInstanceMigrationDocument doc, String defId) {\n    return doc != null && defId != null;\n}","tryCatchPattern":"try {\n    execute(new HistoricCaseInstanceMigrationBatchCmd(doc, defId, cfg));\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"migration document\")) {\n        throw new ConfigurationException(\"Migration document missing; complete the builder chain\", e);\n    }\n    throw e;\n}","preventionTips":["Always finish the migration builder chain with build()","Null-check the fromJson() result when loading documents from files","Keep migration document construction and command invocation in one validated helper method"],"tags":["flowable","cmmn","null-argument","case-migration","migration-document"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}