{"record":{"id":"69fbd84b86ac5d18","repo":"flowable/flowable-engine","slug":"could-not-lock-case-instance","errorCode":null,"errorMessage":"Could not lock case instance","messagePattern":"Could not lock case instance","errorType":"exception","errorClass":"FlowableOptimisticLockingException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/persistence/entity/data/impl/MybatisCaseInstanceDataManagerImpl.java","lineNumber":198,"sourceCode":"    }\n\n    @Override\n    public long countByCriteria(CaseInstanceQueryImpl query) {\n        setSafeInValueLists(query);\n        return (Long) getDbSqlSession().selectOne(\"selectCaseInstanceCountByQueryCriteria\", query);\n    }\n\n    @Override\n    public void updateLockTime(String caseInstanceId, Date lockDate, String lockOwner, Date expirationTime) {\n        HashMap<String, Object> params = new HashMap<>();\n        params.put(\"id\", caseInstanceId);\n        params.put(\"lockTime\", lockDate);\n        params.put(\"expirationTime\", expirationTime);\n        params.put(\"lockOwner\", lockOwner);\n\n        int result = getDbSqlSession().directUpdate(\"updateCaseInstanceLockTime\", params);\n        if (result == 0) {\n            throw new FlowableOptimisticLockingException(\"Could not lock case instance\");\n        }\n    }\n\n    @Override\n    public void clearLockTime(String caseInstanceId) {\n        HashMap<String, Object> params = new HashMap<>();\n        params.put(\"id\", caseInstanceId);\n        getDbSqlSession().directUpdate(\"clearCaseInstanceLockTime\", params);\n    }\n\n    @Override\n    public void clearAllLockTimes(String lockOwner) {\n        HashMap<String, Object> params = new HashMap<>();\n        params.put(\"lockOwner\", lockOwner);\n        getDbSqlSession().directUpdate(\"clearAllCaseInstanceLockTimes\", params);\n    }\n\n    protected void setSafeInValueLists(CaseInstanceQueryImpl caseInstanceQuery) {","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/persistence/entity/data/impl/MybatisCaseInstanceDataManagerImpl.java#L180-L216","documentation":"Thrown by MybatisCaseInstanceDataManagerImpl.updateLockTime when the directUpdate on updateCaseInstanceLockTime affects 0 rows. This is an optimistic-locking style failure: the engine tried to acquire a lock on a case instance but the row no longer matches the expected state (deleted or concurrently locked).","triggerScenarios":"Calling updateLockTime(caseInstanceId, ...) when the case instance row has already been deleted or its LOCK_TIME_/LOCK_OWNER_/EXPIRATION_TIME_ state changed concurrently so the conditional update matched nothing.","commonSituations":"Long-running or heavily concurrent case operations where two threads race for the lock; stale entity references after a case instance was terminated and removed; distributed engine nodes with unsynchronized caches.","solutions":["Retry the operation after re-fetching the case instance to confirm it still exists","Catch FlowableOptimisticLockingException and treat it as 'another node holds the lock', rescheduling the work","Verify the case instance was not concurrently deleted before attempting to lock"],"exampleFix":"// before\nentityManager.updateLockTime(caseInstanceId, lockOwner, lockDate, expirationTime); // throws if row gone\n// after\ntry {\n    entityManager.updateLockTime(caseInstanceId, lockOwner, lockDate, expirationTime);\n} catch (FlowableOptimisticLockingException e) {\n    // another node locked or the instance was removed; reschedule or skip\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    entityManager.updateLockTime(caseInstanceId, lockOwner, lockDate, expirationTime);\n} catch (FlowableOptimisticLockingException e) {\n    // re-fetch instance; retry with backoff or skip if deleted\n}","preventionTips":["Limit concurrent mutations of the same case instance","Use short transactions around lock acquisition","Detect and surface concurrent case instance deletion instead of blindly locking"],"tags":["cmmn","optimistic-locking","concurrency"],"backgroundTag":"invalid-state-transition","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}