flowable/flowable-engine · error · FlowableException
There are ${count} decisions with key = '${decisionKey}' and
Error message
There are ${count} decisions with key = '${decisionKey}' and version = '${decisionVersion}'. What it means
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.
Source
Thrown at modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/persistence/entity/data/impl/MybatisDecisionDataManager.java:136
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;
}
@Override
@SuppressWarnings("unchecked")
public List<DmnDecision> findDecisionsByNativeQuery(Map<String, Object> parameterMap) {
return getDbSqlSession().selectListWithRawParameter("selectDecisionByNativeQuery", parameterMap);
}
@Override
public long findDecisionCountByNativeQuery(Map<String, Object> parameterMap) {
return (Long) getDbSqlSession().selectOne("selectDecisionCountByNativeQuery", parameterMap);
}
@Override
public void updateDecisionTenantIdForDeployment(String deploymentId, String newTenantId) {
HashMap<String, Object> params = new HashMap<>();View on GitHub (pinned to d6d39ce1c6)
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.
Example fix
// before: duplicate rows for tenant
DecisionEntity d = decisionEntityManager.findDecisionByKeyAndVersionAndTenantId("myTable", 1, "tenant-1");
// after: clean duplicates, then redeploy fresh
dmnRepositoryService.deleteDeployment(dupDeploymentId);
dmnRepositoryService.createDeployment().tenantId("tenant-1")
.addClasspathResource("myTable.dmn").deploy();
DecisionEntity d = decisionEntityManager.findDecisionByKeyAndVersionAndTenantId("myTable", 1, "tenant-1"); Defensive patterns
Strategy: validation
Validate before calling
SELECT COUNT(*) FROM ACT_DMN_DECISION WHERE KEY_ = :key AND VERSION_ = :v AND TENANT_ID_ = :tenant; // run before lookups in tooling; if count > 1, dedupe first
Try / catch
try {
DecisionEntity d = dataManager.findDecisionByKeyAndVersionAndTenantId(key, version, tenantId);
} catch (FlowableException e) {
if (e.getMessage().contains("There are")) {
// dedupe rows for this tenant, then retry once
} else { throw e; }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
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} decision tables with key = '${decisionKey
- Cannot find case definition for id:
- DMN repository service is not available
- There are ${results.size} case definitions with key = '${cas
- There are ${results.size} case definitions with key = '${cas
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8b7d39f62c5302fa.
Report an issue: GitHub.