flowable/flowable-engine · error · FlowableException

Could not acquire lock " + lockName + ". Current lock…

Error message

Could not acquire lock " + lockName + ". Current lock value: " + lockValue

What it means

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.

Solutions

  1. Increase the lock wait time / lockForceAcquireAfter configuration so long operations can complete
  2. Investigate the current lock value printed in the message — identify which node holds it and whether it is stale (dead node)
  3. 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

Example fix

// before (default too short)
engineConfig.setLockWaitTime(10_000);
// after
engineConfig.setLockWaitTime(60_000);
engineConfig.setLockForceAcquireAfter(120_000);
Defensive patterns

Strategy: retry

Validate before calling

// before waiting, check lock holder
String holder = commandExecutor.execute(new GetLockValueCmd(lockName, engineType));
boolean stale = holder == null || lastHeartbeatOlderThan(holder, lockForceAcquireAfter);

Try / catch

try { lockManager.waitForLock(lockName); } catch (FlowableException e) { if (e.getMessage().startsWith("Could not acquire lock")) { alertOps(e.getMessage()); retryWithBackoff(); } else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/653de846ecb21cd3. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/lock/LockManagerImpl.java:85

    @Override
    public void waitForLock(Duration waitTime) {
        long timeToGiveUp = System.currentTimeMillis()+ waitTime.toMillis();
        boolean locked = false;
        while (!locked && (System.currentTimeMillis() < timeToGiveUp)) {
            locked = acquireLock();
            if (!locked) {
                try {
                    Thread.sleep(getLockPollRate().toMillis());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }

        if (!locked) {
            String lockValue = executeCommand(new GetLockValueCmd(lockName, engineType));
            throw new FlowableException("Could not acquire lock " + lockName + ". Current lock value: " + lockValue);
        }
    }

    @Override
    public boolean acquireLock() {
        return acquireLock(lockForceAcquireAfter);
    }

    @Override
    public boolean acquireLock(Duration lockForceAcquireAfter) {
        if (hasAcquiredLock) {
            return true;
        }

        try {
            hasAcquiredLock = executeCommand(new LockCmd(lockName, lockForceAcquireAfter, engineType));
            if (hasAcquiredLock) {
                LOGGER.debug("Successfully acquired lock {}", lockName);

View on GitHub (pinned to d6d39ce1c6)