{"record":{"id":"c28bd5e7beb74db7","repo":"flowable/flowable-engine","slug":"must-specify-a-case-definition-tenant-id-to-migrat-c28bd5","errorCode":null,"errorMessage":"Must specify a case definition tenant id to migrate","messagePattern":"Must specify a case definition tenant id 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":55,"sourceCode":"        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        }\n        this.caseDefinitionKey = caseDefinitionKey;\n        this.caseDefinitionVersion = caseDefinitionVersion;\n        this.caseDefinitionTenantId = caseDefinitionTenantId;\n        this.historicCaseInstanceMigrationDocument = historicCaseInstanceMigrationDocument;\n        this.cmmnEngineConfiguration = cmmnEngineConfiguration;\n    }\n\n    @Override\n    public Batch execute(CommandContext commandContext) {\n        CaseInstanceMigrationManager migrationManager = cmmnEngineConfiguration.getCaseInstanceMigrationManager();\n\n        if (caseDefinitionId != null) {\n            return migrationManager.batchMigrateHistoricCaseInstancesOfCaseDefinition(caseDefinitionId, historicCaseInstanceMigrationDocument, commandContext);\n        } else if (caseDefinitionKey != null && caseDefinitionVersion >= 0) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/HistoricCaseInstanceMigrationBatchCmd.java#L37-L73","documentation":"When batch-migrating by case definition key and version, the tenant id is required to disambiguate the definition among tenants. The key/version/tenant constructor throws this FlowableException when caseDefinitionTenantId is null, because key+version alone may match definitions in multiple tenants.","triggerScenarios":"Calling new HistoricCaseInstanceMigrationBatchCmd(caseDefinitionKey, version, null, document, cfg). Common when the application does not use multi-tenancy and the developer assumes tenant can be omitted.","commonSituations":"Single-tenant setups where tenant ids were never configured; passing empty string vs null confusion; copying a call that omitted the tenant argument.","solutions":["Pass the tenant id the case definition was deployed under (e.g. RepositoryService deploy artifacts with tenant, use the same value here).","For single-tenant/no-tenant deployments, verify the deployed definition's tenant id via createCaseDefinitionQuery().caseDefinitionKey(key).caseDefinitionVersion(v).list() and use the value shown (often empty string or a default tenant).","Alternatively migrate by explicit caseDefinitionId to avoid needing key/version/tenant at all."],"exampleFix":"// before\nnew HistoricCaseInstanceMigrationBatchCmd(\"myCase\", 3, null, doc, cfg); // tenant null\n\n// after\nnew HistoricCaseInstanceMigrationBatchCmd(\"myCase\", 3, \"acme-tenant\", doc, cfg);","handlingStrategy":"validation","validationCode":"if (tenantId == null)\n    throw new IllegalArgumentException(\"tenantId required for key-based historic migration\");","typeGuard":"boolean hasTenant(String tenantId) { return tenantId != null; }","tryCatchPattern":"try {\n    migrateByKeyVersionTenant(key, version, tenantId, doc);\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"tenant id\")) {\n        throw new ConfigurationException(\"Configure the deployment tenant id before migration\", e);\n    }\n    throw e;\n}","preventionTips":["Store the deployment tenant id alongside the definition key/version in your migration config","For multi-tenant systems, iterate tenant ids from TenantQuery instead of assuming one","Remember null is rejected even in single-tenant setups"],"tags":["flowable","cmmn","null-argument","tenant","case-migration"],"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"}