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;
}
@OverrideView on GitHub (pinned to d6d39ce1c6)
Solutions
- Read the wrapped exception in the WARN log to identify the real underlying DB/engine failure and fix that first
- If it's transient contention, nothing to fix — the manager retries; verify lockName and check cluster node count versus lock timeout
- If persistent, verify the lock table exists and the DB user has read/write permission on it
- 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
- Keep lock retention/wait high enough for cluster contention
- Verify DB connectivity and lock-table permissions before startup
- Monitor WARN logs for repeated unknown exceptions — they indicate a persistent non-transient cause
- Avoid many nodes acquiring the same lock at the exact same instant (stagger startup)
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
- Exception while autodeploying DMN definitions. This exceptio
- Exception while autodeploying DMN definitions for resource {
- Error while waiting for global acquire lock for engine {}
- There are app definitions with key = '' and version = ''
- There are ${count} decision tables with key = '${decisionKey
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/488f4774d613ecb5.
Report an issue: GitHub.