{"record":{"id":"653de846ecb21cd3","repo":"flowable/flowable-engine","slug":"could-not-acquire-lock-lockname-current-l","errorCode":null,"errorMessage":"Could not acquire lock \" + lockName + \". Current lock value: \" + lockValue","messagePattern":"Could not acquire lock \" \\+ lockName \\+ \"\\. Current lock value: \" \\+ lockValue","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/lock/LockManagerImpl.java","lineNumber":85,"sourceCode":"\n    @Override\n    public void waitForLock(Duration waitTime) {\n        long timeToGiveUp = System.currentTimeMillis()+ waitTime.toMillis();\n        boolean locked = false;\n        while (!locked && (System.currentTimeMillis() < timeToGiveUp)) {\n            locked = acquireLock();\n            if (!locked) {\n                try {\n                    Thread.sleep(getLockPollRate().toMillis());\n                } catch (InterruptedException e) {\n                    Thread.currentThread().interrupt();\n                }\n            }\n        }\n\n        if (!locked) {\n            String lockValue = executeCommand(new GetLockValueCmd(lockName, engineType));\n            throw new FlowableException(\"Could not acquire lock \" + lockName + \". Current lock value: \" + lockValue);\n        }\n    }\n\n    @Override\n    public boolean acquireLock() {\n        return acquireLock(lockForceAcquireAfter);\n    }\n\n    @Override\n    public boolean acquireLock(Duration lockForceAcquireAfter) {\n        if (hasAcquiredLock) {\n            return true;\n        }\n\n        try {\n            hasAcquiredLock = executeCommand(new LockCmd(lockName, lockForceAcquireAfter, engineType));\n            if (hasAcquiredLock) {\n                LOGGER.debug(\"Successfully acquired lock {}\", lockName);","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/lock/LockManagerImpl.java#L67-L103","documentation":"LockManagerImpl.waitForLock uses optimistic locking on a shared lock row (per lockName/engineType). If it cannot acquire the lock within the configured wait/attempt budget, it reads the current lock value with GetLockValueCmd and throws FlowableException naming the lock and its current holder value. This typically means another node/thread holds the lock longer than the wait allows, or the lock row was left behind by a crashed owner.","triggerScenarios":"Multiple engine nodes competing for the same lock (e.g. async executor, history cleanup, schema upgrade) where the holder keeps refreshing the lock past lockForceAcquireAfter; a crashed node left the lock value not reset; misconfigured wait time too short for the operation duration.","commonSituations":"Cluster deployments where one node runs a long history-cleanup/job-acquisition while another waits; after an abrupt kill of the lock-holding node without releasing; lock table (ACT_GE_PROPERTY / engine property) rows out of sync.","solutions":["Increase the lock wait time / lockForceAcquireAfter configuration so long operations can complete","Investigate the current lock value printed in the message — identify which node holds it and whether it is stale (dead node)","Restart/reconcile the environment: if the holder is dead, clear the stale lock row or force-acquire by configuration; ensure all nodes run the same Flowable version"],"exampleFix":"// before (default too short)\nengineConfig.setLockWaitTime(10_000);\n// after\nengineConfig.setLockWaitTime(60_000);\nengineConfig.setLockForceAcquireAfter(120_000);","handlingStrategy":"retry","validationCode":"// before waiting, check lock holder\nString holder = commandExecutor.execute(new GetLockValueCmd(lockName, engineType));\nboolean stale = holder == null || lastHeartbeatOlderThan(holder, lockForceAcquireAfter);","typeGuard":null,"tryCatchPattern":"try { lockManager.waitForLock(lockName); } catch (FlowableException e) { if (e.getMessage().startsWith(\"Could not acquire lock\")) { alertOps(e.getMessage()); retryWithBackoff(); } else throw e; }","preventionTips":["Tune lockWaitTime and lockForceAcquireAfter to exceed the longest protected operation","Monitor the lock table and alert on stale lock values","Ensure nodes shut down gracefully so locks are released; pin schema-migration locks to one node"],"tags":["locking","concurrency","cluster","timeout"],"backgroundTag":"request-timeout","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"}