flowable/flowable-engine · critical · ActivitiException
There are process definitions with key = ' ' and version =…
Error message
There are <n> process definitions with key = '<processDefinitionKey>' and version = '<processDefinitionVersion>'.
What it means
findProcessDefinitionByKeyAndVersion expects exactly one process definition matching key and version. If the query returns more than one row the data is inconsistent (a unique key+version pair was violated), and the engine throws ActivitiException rather than guessing which definition to use.
Solutions
- Find duplicates: SELECT KEY_, VERSION_, COUNT(*) FROM ACT_RE_PROCDEF GROUP BY KEY_, VERSION_ HAVING COUNT(*) > 1; delete/archive the extra rows keeping one correct definition.
- Never insert process-definition rows manually — deploy via the RepositoryService/deployment API so the engine assigns versions.
- Verify deployed definitions with repositoryService.createProcessDefinitionQuery().processDefinitionKey(k).list() to spot duplicates early.
- Use processDefinitionKey + latest-version query (or processDefinitionId) instead of key+version when duplicates may exist.
Defensive patterns
Strategy: fallback
Validate before calling
List<ProcessDefinition> defs = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(key).processDefinitionVersion(version).list();
if (defs.size() > 1) throw new IllegalStateException("duplicate definitions for key=" + key);
if (defs.isEmpty()) return null; Try / catch
try {
def = repo.getProcessDefinitionByKeyAndVersion(key, version);
} catch (ActivitiException e) {
// fall back to latest version for the key
def = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key)
.latestVersion().singleResult();
} Prevention
- Never insert ACT_RE_PROCDEF rows manually; deploy via the API
- Monitor for duplicate key+version rows with a scheduled SQL check
- Use processDefinitionId or latestVersion queries for resilience
When it happens
Trigger: Querying with a key+version that matches multiple rows in ACT_RE_PROCDEF — normally impossible, but seen after manual DB inserts, restored backups, botched upgrades, or custom deployment code bypassing uniqueness.
Common situations: Database restores that re-imported the same definition rows; manual SQL fixes on ACT_RE_PROCDEF; custom deployment tooling inserting definitions without the engine's uniqueness handling; upgrade scripts partially applied leaving duplicate 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
- Cannot get process definition for id for
- deployment for process definition does not exist
- Error deserializing json info for process definition +…
- No deployed process definition found for key
- no deployed process definition found with id
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/47adb11cceea248c.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionEntityManager.java:97
}
public ProcessDefinitionEntity findProcessDefinitionByDeploymentAndKeyAndTenantId(String deploymentId, String processDefinitionKey, String tenantId) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("deploymentId", deploymentId);
parameters.put("processDefinitionKey", processDefinitionKey);
parameters.put("tenantId", tenantId);
return (ProcessDefinitionEntity) getDbSqlSession().selectOne("selectProcessDefinitionByDeploymentAndKeyAndTenantId", parameters);
}
public ProcessDefinition findProcessDefinitionByKeyAndVersion(String processDefinitionKey, Integer processDefinitionVersion) {
ProcessDefinitionQueryImpl processDefinitionQuery = new ProcessDefinitionQueryImpl()
.processDefinitionKey(processDefinitionKey)
.processDefinitionVersion(processDefinitionVersion);
List<ProcessDefinition> results = findProcessDefinitionsByQueryCriteria(processDefinitionQuery, null);
if (results.size() == 1) {
return results.get(0);
} else if (results.size() > 1) {
throw new ActivitiException("There are " + results.size() + " process definitions with key = '" + processDefinitionKey + "' and version = '" + processDefinitionVersion + "'.");
}
return null;
}
public List<ProcessDefinition> findProcessDefinitionsStartableByUser(String user) {
return new ProcessDefinitionQueryImpl().startableByUser(user).list();
}
@SuppressWarnings("unchecked")
public List<ProcessDefinition> findProcessDefinitionsByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults) {
return getDbSqlSession().selectListWithRawParameter("selectProcessDefinitionByNativeQuery", parameterMap, firstResult, maxResults);
}
public long findProcessDefinitionCountByNativeQuery(Map<String, Object> parameterMap) {
return (Long) getDbSqlSession().selectOne("selectProcessDefinitionCountByNativeQuery", parameterMap);
}
public void updateProcessDefinitionTenantIdForDeployment(String deploymentId, String newTenantId) {View on GitHub (pinned to d6d39ce1c6)