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

  1. Inspect duplicates: SELECT * FROM ACT_DMN_DECISION WHERE KEY_='<key>' AND VERSION_=<v> AND TENANT_ID_='<tenant>'; remove the stale rows.
  2. Delete the offending deployments through DmnRepositoryService.deleteDeployment and redeploy so versioning is recalculated.
  3. Fix deployment tooling so each redeploy either increments version or reuses the existing definition instead of inserting a duplicate row.
  4. 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

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/8b7d39f62c5302fa. Report an issue: GitHub.