flowable/flowable-engine · error · FlowableException
There are ${count} decision tables with key = '${decisionKey
Error message
There are ${count} decision tables with key = '${decisionKey}' and version = '${decisionVersion}'. What it means
Flowable's DMN engine found more than one row in ACT_DMN_DECISION with the same key and version when looking up a decision table via findDecisionByKeyAndVersion. The (KEY_, VERSION_) pair is expected to identify at most one deployed decision definition; duplicates indicate corrupted or manually duplicated deployment data. The engine throws FlowableException instead of guessing which definition to use.
Source
Thrown at modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/persistence/entity/data/impl/MybatisDecisionDataManager.java:120
@Override
public DecisionEntity findDecisionByDeploymentAndKeyAndTenantId(String deploymentId, String decisionKey, String tenantId) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("deploymentId", deploymentId);
parameters.put("decisionKey", decisionKey);
parameters.put("tenantId", tenantId);
return (DecisionEntity) getDbSqlSession().selectOne("selectDecisionByDeploymentAndKeyAndTenantId", parameters);
}
@Override
public DecisionEntity findDecisionByKeyAndVersion(String decisionKey, Integer decisionVersion) {
Map<String, Object> params = new HashMap<>();
params.put("decisionKey", decisionKey);
params.put("decisionVersion", decisionVersion);
List<DecisionEntity> results = getDbSqlSession().selectList("selectDecisionsByKeyAndVersion", params);
if (results.size() == 1) {
return results.get(0);
} else if (results.size() > 1) {
throw new FlowableException("There are " + results.size() + " decision tables with key = '" + decisionKey + "' and version = '" + decisionVersion + "'.");
}
return null;
}
@Override
@SuppressWarnings("unchecked")
public DecisionEntity findDecisionByKeyAndVersionAndTenantId(String decisionKey, Integer decisionVersion, String tenantId) {
Map<String, Object> params = new HashMap<>();
params.put("decisionKey", decisionKey);
params.put("decisionVersion", decisionVersion);
params.put("tenantId", tenantId);
List<DecisionEntity> results = getDbSqlSession().selectList("selectDecisionsByKeyAndVersionAndTenantId", params);
if (results.size() == 1) {
return results.get(0);
} else if (results.size() > 1) {
throw new FlowableException("There are " + results.size() + " decisions with key = '" + decisionKey + "' and version = '" + decisionVersion + "'.");
}
return null;View on GitHub (pinned to d6d39ce1c6)
Solutions
- Query the DB and remove/merge duplicate rows: SELECT * FROM ACT_DMN_DECISION WHERE KEY_ = '<key>' AND VERSION_ = <version>; delete the stale duplicates.
- Redeploy the decision table cleanly: delete the duplicate deployments via the DMN repository API (DmnRepositoryService.deleteDeployment) so version management regenerates unique rows.
- If duplicates are across tenants, switch to findDecisionByKeyAndVersionAndTenantId or set the tenant ID on the deployment so lookups are scoped.
- Audit deployment scripts to ensure they do not force a fixed version or redeploy identical resources producing duplicate (key, version) rows.
Example fix
// before: lookup fails due to duplicates
DecisionEntity d = decisionEntityManager.findDecisionByKeyAndVersion("myTable", 1);
// after: scope by tenant / ensure unique version at deploy time
DmnDeployment dep = dmnRepositoryService.createDeployment()
.tenantId("tenant-1")
.addClasspathResource("diagrams/myTable.dmn")
.deploy();
DecisionEntity d = decisionEntityManager.findDecisionByKeyAndVersionAndTenantId("myTable", 1, "tenant-1"); Defensive patterns
Strategy: validation
Validate before calling
List<DecisionEntity> dupes = dmnManagementService // or direct SQL
.executeCommand(ctx -> ctx.getDbSqlSession().selectList("selectDecisionsByKeyAndVersion",
Map.of("decisionKey", key, "decisionVersion", version)));
if (dupes == null || dupes.size() > 1) {
throw new IllegalStateException("Duplicate DMN decisions for " + key + " v" + version + ": clean up ACT_DMN_DECISION before lookup");
} Try / catch
try {
DecisionEntity d = dataManager.findDecisionByKeyAndVersion(key, version);
} catch (FlowableException e) {
if (e.getMessage().contains("There are")) {
// run dedup/cleanup of duplicate ACT_DMN_DECISION rows, then retry
} else { throw e; }
} Prevention
- Never insert directly into ACT_DMN_DECISION; always deploy via DmnRepositoryService so versions are managed.
- Do not force fixed version numbers in deployment scripts.
- Scope deployments and lookups with tenantId when running multi-tenant.
- Add a unique-constraint/audit check on (KEY_, VERSION_, TENANT_ID_) in your DB migrations.
When it happens
Trigger: Calling findDecisionByKeyAndVersion (directly or through DMN rule/decision-table resolution APIs) when the DMN_DECISION table contains 2+ rows sharing the same KEY_ and VERSION_, e.g. after deploying the same decision table XML twice without redeploying (deployments with same resource forcing same version), manual DB copies, or imported data across environments.
Common situations: Database restored/merged from two environments with the same deployments; bulk import scripts that insert decision rows directly bypassing deployment versioning; deployment duplication caused by re-running deployment scripts with a fixed version label; multi-tenant data copied without tenant scoping (this variant has no tenant filter).
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- There are ${count} decisions with key = '${decisionKey}' and
- No decision table found with id ${decisionTableId}
- Exception while autodeploying DMN definitions. This exceptio
- Exception while autodeploying DMN definitions for resource {
- There are app definitions with key = '' and version = ''
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/62af916bcb6339ae.
Report an issue: GitHub.