flowable/flowable-engine · error · FlowableException

There are process definitions with key = '' and version =…

Error message

There are  process definitions with key = '' and version = ''.

What it means

findProcessDefinitionByKeyAndVersion expects at most one process definition for a given key and version. If the query 'selectProcessDefinitionsByKeyAndVersion' returns more than one row, the data is inconsistent (duplicated definitions for the same key/version) and a FlowableException is thrown listing the count, key and version.

Solutions

  1. Inspect ACT_RE_PROCDEF: SELECT * FROM ACT_RE_PROCDEF WHERE KEY_ = '<key>' AND VERSION_ = <version>; delete/archive duplicate rows keeping exactly one.
  2. Identify how duplicates were created (manual inserts, DB merge) and prevent it; rely on engine-generated versioning only.
  3. If multi-tenant, use the tenant-aware lookup (findProcessDefinitionByKeyAndVersionAndTenantId) or include tenant id in queries.
  4. Restore from a clean backup of ACT_RE_PROCDEF if duplicates are widespread.

Example fix

// before
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).processDefinitionVersion(ver).singleResult(); // may hide duplicates
// after: dedupe in DB
// DELETE FROM ACT_RE_PROCDEF WHERE ID_ = '<duplicate-id>'; -- keep one row per (KEY_, VERSION_)
Defensive patterns

Strategy: validation

Validate before calling

long n = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).processDefinitionVersion(ver).count();
if (n > 1) throw new IllegalStateException("Duplicate process definitions for key=" + key + " version=" + ver);
if (n == 0) throw new IllegalStateException("No process definition for key=" + key + " version=" + ver);

Prevention

When it happens

Trigger: Calling RepositoryService.getProcessDefinitionByKeyAndVersion-style lookups (or deployment resolution paths using this manager method) when the ACT_RE_PROCDEF table contains duplicate rows with the same KEY_ and VERSION_ — e.g. after a bad restore, manual data manipulation, or deployment concurrency bugs in older versions.

Common situations: Database restored/merged from two environments producing duplicate definition rows; manual SQL inserts into ACT_RE_PROCDEF; a historical Flowable bug or concurrent deployment race creating duplicates; tenant mismatches where the non-tenant lookup hits multi-tenant rows.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/entity/data/impl/MybatisProcessDefinitionDataManager.java:134

    @Override
    public ProcessDefinitionEntity findProcessDefinitionByParentDeploymentAndKeyAndTenantId(String parentDeploymentId, String processDefinitionKey, String tenantId) {
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("parentDeploymentId", parentDeploymentId);
        parameters.put("processDefinitionKey", processDefinitionKey);
        parameters.put("tenantId", tenantId);
        return (ProcessDefinitionEntity) getDbSqlSession().selectOne("selectProcessDefinitionByParentDeploymentAndKeyAndTenantId", parameters);
    }

    @Override
    public ProcessDefinitionEntity findProcessDefinitionByKeyAndVersion(String processDefinitionKey, Integer processDefinitionVersion) {
        Map<String, Object> params = new HashMap<>();
        params.put("processDefinitionKey", processDefinitionKey);
        params.put("processDefinitionVersion", processDefinitionVersion);
        List<ProcessDefinitionEntity> results = getDbSqlSession().selectList("selectProcessDefinitionsByKeyAndVersion", params);
        if (results.size() == 1) {
            return results.get(0);
        } else if (results.size() > 1) {
            throw new FlowableException("There are " + results.size() + " process definitions with key = '" + processDefinitionKey + "' and version = '" + processDefinitionVersion + "'.");
        }
        return null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public ProcessDefinitionEntity findProcessDefinitionByKeyAndVersionAndTenantId(String processDefinitionKey, Integer processDefinitionVersion, String tenantId) {
        Map<String, Object> params = new HashMap<>();
        params.put("processDefinitionKey", processDefinitionKey);
        params.put("processDefinitionVersion", processDefinitionVersion);
        params.put("tenantId", tenantId);
        List<ProcessDefinitionEntity> results = getDbSqlSession().selectList("selectProcessDefinitionsByKeyAndVersionAndTenantId", params);
        if (results.size() == 1) {
            return results.get(0);
        } else if (results.size() > 1) {
            throw new FlowableException("There are " + results.size() + " process definitions with key = '" + processDefinitionKey + "' and version = '" + processDefinitionVersion + "' in tenant='" + tenantId + "'.");
        }
        return null;

View on GitHub (pinned to d6d39ce1c6)