{"record":{"id":"47adb11cceea248c","repo":"flowable/flowable-engine","slug":"there-are-n-process-definitions-with-key-pro","errorCode":null,"errorMessage":"There are <n> process definitions with key = '<processDefinitionKey>' and version = '<processDefinitionVersion>'.","messagePattern":"There are <n> process definitions with key = '<processDefinitionKey>' and version = '<processDefinitionVersion>'\\.","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"critical","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionEntityManager.java","lineNumber":97,"sourceCode":"    }\n\n    public ProcessDefinitionEntity findProcessDefinitionByDeploymentAndKeyAndTenantId(String deploymentId, String processDefinitionKey, String tenantId) {\n        Map<String, Object> parameters = new HashMap<>();\n        parameters.put(\"deploymentId\", deploymentId);\n        parameters.put(\"processDefinitionKey\", processDefinitionKey);\n        parameters.put(\"tenantId\", tenantId);\n        return (ProcessDefinitionEntity) getDbSqlSession().selectOne(\"selectProcessDefinitionByDeploymentAndKeyAndTenantId\", parameters);\n    }\n\n    public ProcessDefinition findProcessDefinitionByKeyAndVersion(String processDefinitionKey, Integer processDefinitionVersion) {\n        ProcessDefinitionQueryImpl processDefinitionQuery = new ProcessDefinitionQueryImpl()\n                .processDefinitionKey(processDefinitionKey)\n                .processDefinitionVersion(processDefinitionVersion);\n        List<ProcessDefinition> results = findProcessDefinitionsByQueryCriteria(processDefinitionQuery, null);\n        if (results.size() == 1) {\n            return results.get(0);\n        } else if (results.size() > 1) {\n            throw new ActivitiException(\"There are \" + results.size() + \" process definitions with key = '\" + processDefinitionKey + \"' and version = '\" + processDefinitionVersion + \"'.\");\n        }\n        return null;\n    }\n\n    public List<ProcessDefinition> findProcessDefinitionsStartableByUser(String user) {\n        return new ProcessDefinitionQueryImpl().startableByUser(user).list();\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public List<ProcessDefinition> findProcessDefinitionsByNativeQuery(Map<String, Object> parameterMap, int firstResult, int maxResults) {\n        return getDbSqlSession().selectListWithRawParameter(\"selectProcessDefinitionByNativeQuery\", parameterMap, firstResult, maxResults);\n    }\n\n    public long findProcessDefinitionCountByNativeQuery(Map<String, Object> parameterMap) {\n        return (Long) getDbSqlSession().selectOne(\"selectProcessDefinitionCountByNativeQuery\", parameterMap);\n    }\n\n    public void updateProcessDefinitionTenantIdForDeployment(String deploymentId, String newTenantId) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ProcessDefinitionEntityManager.java#L79-L115","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"List<ProcessDefinition> defs = repositoryService.createProcessDefinitionQuery()\n    .processDefinitionKey(key).processDefinitionVersion(version).list();\nif (defs.size() > 1) throw new IllegalStateException(\"duplicate definitions for key=\" + key);\nif (defs.isEmpty()) return null;","typeGuard":null,"tryCatchPattern":"try {\n    def = repo.getProcessDefinitionByKeyAndVersion(key, version);\n} catch (ActivitiException e) {\n    // fall back to latest version for the key\n    def = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key)\n        .latestVersion().singleResult();\n}","preventionTips":["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"],"tags":["process-definition","database","duplicate-data","deployment"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}