{"record":{"id":"0cc98012b9267a50","repo":"flowable/flowable-engine","slug":"there-are-process-definitions-with-key-and-v","errorCode":null,"errorMessage":"There are  process definitions with key = '' and version = ''.","messagePattern":"There are  process definitions with key = '' and version = ''\\.","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/entity/data/impl/MybatisProcessDefinitionDataManager.java","lineNumber":134,"sourceCode":"    @Override\n    public ProcessDefinitionEntity findProcessDefinitionByParentDeploymentAndKeyAndTenantId(String parentDeploymentId, String processDefinitionKey, String tenantId) {\n        Map<String, Object> parameters = new HashMap<>();\n        parameters.put(\"parentDeploymentId\", parentDeploymentId);\n        parameters.put(\"processDefinitionKey\", processDefinitionKey);\n        parameters.put(\"tenantId\", tenantId);\n        return (ProcessDefinitionEntity) getDbSqlSession().selectOne(\"selectProcessDefinitionByParentDeploymentAndKeyAndTenantId\", parameters);\n    }\n\n    @Override\n    public ProcessDefinitionEntity findProcessDefinitionByKeyAndVersion(String processDefinitionKey, Integer processDefinitionVersion) {\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"processDefinitionKey\", processDefinitionKey);\n        params.put(\"processDefinitionVersion\", processDefinitionVersion);\n        List<ProcessDefinitionEntity> results = getDbSqlSession().selectList(\"selectProcessDefinitionsByKeyAndVersion\", params);\n        if (results.size() == 1) {\n            return results.get(0);\n        } else if (results.size() > 1) {\n            throw new FlowableException(\"There are \" + results.size() + \" process definitions with key = '\" + processDefinitionKey + \"' and version = '\" + processDefinitionVersion + \"'.\");\n        }\n        return null;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public ProcessDefinitionEntity findProcessDefinitionByKeyAndVersionAndTenantId(String processDefinitionKey, Integer processDefinitionVersion, String tenantId) {\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"processDefinitionKey\", processDefinitionKey);\n        params.put(\"processDefinitionVersion\", processDefinitionVersion);\n        params.put(\"tenantId\", tenantId);\n        List<ProcessDefinitionEntity> results = getDbSqlSession().selectList(\"selectProcessDefinitionsByKeyAndVersionAndTenantId\", params);\n        if (results.size() == 1) {\n            return results.get(0);\n        } else if (results.size() > 1) {\n            throw new FlowableException(\"There are \" + results.size() + \" process definitions with key = '\" + processDefinitionKey + \"' and version = '\" + processDefinitionVersion + \"' in tenant='\" + tenantId + \"'.\");\n        }\n        return null;","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/entity/data/impl/MybatisProcessDefinitionDataManager.java#L116-L152","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect ACT_RE_PROCDEF: SELECT * FROM ACT_RE_PROCDEF WHERE KEY_ = '<key>' AND VERSION_ = <version>; delete/archive duplicate rows keeping exactly one.","Identify how duplicates were created (manual inserts, DB merge) and prevent it; rely on engine-generated versioning only.","If multi-tenant, use the tenant-aware lookup (findProcessDefinitionByKeyAndVersionAndTenantId) or include tenant id in queries.","Restore from a clean backup of ACT_RE_PROCDEF if duplicates are widespread."],"exampleFix":"// before\nProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).processDefinitionVersion(ver).singleResult(); // may hide duplicates\n// after: dedupe in DB\n// DELETE FROM ACT_RE_PROCDEF WHERE ID_ = '<duplicate-id>'; -- keep one row per (KEY_, VERSION_)","handlingStrategy":"validation","validationCode":"long n = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).processDefinitionVersion(ver).count();\nif (n > 1) throw new IllegalStateException(\"Duplicate process definitions for key=\" + key + \" version=\" + ver);\nif (n == 0) throw new IllegalStateException(\"No process definition for key=\" + key + \" version=\" + ver);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never manually INSERT into ACT_RE_PROCDEF","Audit the table for duplicate (KEY_, VERSION_) pairs after restores/merges","Use engine-managed versioning via deployments only"],"tags":["process-definition","data-integrity","persistence"],"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"}