{"record":{"id":"8b7d39f62c5302fa","repo":"flowable/flowable-engine","slug":"there-are-count-decisions-with-key-decisio","errorCode":null,"errorMessage":"There are ${count} decisions with key = '${decisionKey}' and version = '${decisionVersion}'.","messagePattern":"There are (.+?) decisions with key = '(.+?)' and version = '(.+?)'\\.","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/persistence/entity/data/impl/MybatisDecisionDataManager.java","lineNumber":136,"sourceCode":"            return results.get(0);\n        } else if (results.size() > 1) {\n            throw new FlowableException(\"There are \" + results.size() + \" decision tables with key = '\" + decisionKey + \"' and version = '\" + decisionVersion + \"'.\");\n        }\n        return null;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public DecisionEntity findDecisionByKeyAndVersionAndTenantId(String decisionKey, Integer decisionVersion, String tenantId) {\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"decisionKey\", decisionKey);\n        params.put(\"decisionVersion\", decisionVersion);\n        params.put(\"tenantId\", tenantId);\n        List<DecisionEntity> results = getDbSqlSession().selectList(\"selectDecisionsByKeyAndVersionAndTenantId\", params);\n        if (results.size() == 1) {\n            return results.get(0);\n        } else if (results.size() > 1) {\n            throw new FlowableException(\"There are \" + results.size() + \" decisions with key = '\" + decisionKey + \"' and version = '\" + decisionVersion + \"'.\");\n        }\n        return null;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public List<DmnDecision> findDecisionsByNativeQuery(Map<String, Object> parameterMap) {\n        return getDbSqlSession().selectListWithRawParameter(\"selectDecisionByNativeQuery\", parameterMap);\n    }\n\n    @Override\n    public long findDecisionCountByNativeQuery(Map<String, Object> parameterMap) {\n        return (Long) getDbSqlSession().selectOne(\"selectDecisionCountByNativeQuery\", parameterMap);\n    }\n\n    @Override\n    public void updateDecisionTenantIdForDeployment(String deploymentId, String newTenantId) {\n        HashMap<String, Object> params = new HashMap<>();","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/persistence/entity/data/impl/MybatisDecisionDataManager.java#L118-L154","documentation":"The tenant-scoped variant of the decision lookup, findDecisionByKeyAndVersionAndTenantId, found more than one decision definition row with the same key, version AND tenant ID. Since key+version+tenant should be unique, this signals duplicate DMN decision rows for that tenant. Flowable refuses to pick one arbitrarily and throws FlowableException.","triggerScenarios":"Calling findDecisionByKeyAndVersionAndTenantId (or deploying/evaluating decisions with a tenantId) when ACT_DMN_DECISION contains 2+ rows with identical KEY_, VERSION_ and TENANT_ID_, typically from repeated deployments that force the same version or direct DB manipulation/import.","commonSituations":"Tenant-scoped deployment scripts re-run against the same tenant without cleanup; environment data merges copying a tenant's decision rows twice; custom import tools that insert into ACT_DMN_DECISION without enforcing the unique constraint.","solutions":["Inspect duplicates: SELECT * FROM ACT_DMN_DECISION WHERE KEY_='<key>' AND VERSION_=<v> AND TENANT_ID_='<tenant>'; remove the stale rows.","Delete the offending deployments through DmnRepositoryService.deleteDeployment and redeploy so versioning is recalculated.","Fix deployment tooling so each redeploy either increments version or reuses the existing definition instead of inserting a duplicate row.","If the lookup should be broader, call findDecisionByKeyAndVersion or drop the tenant filter intentionally after validating data."],"exampleFix":"// before: duplicate rows for tenant\nDecisionEntity d = decisionEntityManager.findDecisionByKeyAndVersionAndTenantId(\"myTable\", 1, \"tenant-1\");\n\n// after: clean duplicates, then redeploy fresh\ndmnRepositoryService.deleteDeployment(dupDeploymentId);\ndmnRepositoryService.createDeployment().tenantId(\"tenant-1\")\n    .addClasspathResource(\"myTable.dmn\").deploy();\nDecisionEntity d = decisionEntityManager.findDecisionByKeyAndVersionAndTenantId(\"myTable\", 1, \"tenant-1\");","handlingStrategy":"validation","validationCode":"SELECT COUNT(*) FROM ACT_DMN_DECISION WHERE KEY_ = :key AND VERSION_ = :v AND TENANT_ID_ = :tenant;\n// run before lookups in tooling; if count > 1, dedupe first","typeGuard":null,"tryCatchPattern":"try {\n    DecisionEntity d = dataManager.findDecisionByKeyAndVersionAndTenantId(key, version, tenantId);\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"There are\")) {\n        // dedupe rows for this tenant, then retry once\n    } else { throw e; }\n}","preventionTips":["Always set tenantId on deployments so tenant-scoped lookups stay unique.","Use DmnRepositoryService.deleteDeployment to remove old tenant deployments instead of SQL deletes.","Add a DB unique index on (KEY_, VERSION_, TENANT_ID_).","Validate tenant data imports for duplicate decision keys before merging environments."],"tags":["flowable","dmn","multi-tenant","duplicate-records"],"backgroundTag":"database-query-failed","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}