flowable/flowable-engine · error

Failed to acquire lock {} due to unknown exception

Error message

Failed to acquire lock {} due to unknown exception

What it means

LockManagerImpl.acquireLock retries acquiring a named lock (typically a DB row with optimistic locking). A generic FlowableException (exactly FlowableException, not a subclass) is treated as a transient failure: it is logged as a warning and the lock acquisition is retried after a wait. The error indicates the underlying lock acquisition failed for a non-optimistic-lock reason.

Source

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

    @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);
            }
        } catch (FlowableOptimisticLockingException ex) {
            LOGGER.debug("Failed to acquire lock {} due to optimistic locking", lockName, ex);
            hasAcquiredLock = false;
        } catch (FlowableException ex) {
            if (ex.getClass().equals(FlowableException.class)) {
                // If it is a FlowableException then log a warning and wait to try again
                LOGGER.warn("Failed to acquire lock {} due to unknown exception", lockName, ex);
                hasAcquiredLock = false;
            } else {
                // Re-throw any other Flowable specific exception
                throw ex;
            }
        } catch (RuntimeException ex) {
            if (ex.getCause() instanceof SQLIntegrityConstraintViolationException) {
                // This can happen if 2 nodes try to acquire a lock in the exact same time
                LOGGER.debug("Failed to acquire lock {} due to constraint violation", lockName, ex);
            } else {
                LOGGER.info("Failed to acquire lock {} due to unknown exception", lockName, ex);
            }
            hasAcquiredLock = false;
        }
        return hasAcquiredLock;
    }

    @Override

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Read the wrapped exception in the WARN log to identify the real underlying DB/engine failure and fix that first
  2. If it's transient contention, nothing to fix — the manager retries; verify lockName and check cluster node count versus lock timeout
  3. If persistent, verify the lock table exists and the DB user has read/write permission on it
  4. Check the configured lock wait/retry (defaultLockTime / retry settings) and increase if contention is expected
Defensive patterns

Strategy: retry

Try / catch

// acquireLock already retries internally; catch only terminal failures
try {
    lockManager.acquireLock(lockName, lockOwner);
} catch (FlowableOptimisticLockingException | FlowableInterruptedException e) {
    // non-retryable: abort or reschedule
    log.warn("lock permanently unavailable: {}", lockName, e);
}

Prevention

When it happens

Trigger: commandExecutor executing the acquire-lock logic throws a plain FlowableException from a lower layer (e.g. job/lock table access problem) while looping in acquireLock.

Common situations: Database connectivity hiccups or lock-contention during async executor startup; multiple cluster nodes contending for the same lock (e.g. async history or global acquire lock); schema issues in ACT_GE_PROPERTY/lock tables.

Related errors


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