flowable/flowable-engine · warning
Error while waiting for global acquire lock for engine {}
Error message
Error while waiting for global acquire lock for engine {} What it means
WARN log from the timer-job acquisition runnable while waiting for the global acquire lock: a non-FlowableException was thrown during the lock-wait phase and it is logged because it likely indicates a real problem, not the regular (expected) lock-contention path. The cycle simply continues and retries the lock next round.
Source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/AcquireTimerJobsRunnable.java:173
long millisToWait = 0L;
try {
boolean globalAcquireLockEnabled = configuration.isGlobalAcquireLockEnabled();
if (globalAcquireLockEnabled) {
// When running with global acquire lock, we only need to have the lock during the acquire.
// In the move phase, other nodes can already acquire timer jobs themselves (as the lock is free).
try {
timerJobs = lockManager.waitForLockRunAndRelease(configuration.getLockWaitTime(), () -> {
return commandExecutor.execute(new AcquireTimerJobsWithGlobalAcquireLockCmd(asyncExecutor));
});
} catch (Exception e) {
// Don't do anything, lock will be tried again next time
if (!(e instanceof FlowableException)) { // FlowableException doesn't need to be logged, could be regular lock logic
LOGGER.warn("Error while waiting for global acquire lock for engine {}", getEngineName(), e);
}
}
} else {
timerJobs = commandExecutor.execute(new AcquireTimerJobsCmd(asyncExecutor));
}
if (!timerJobs.isEmpty()) {
List<TimerJobEntity> finalTimerJobs = timerJobs;
moveTimerJobsExecutorService.execute(() -> {
executeMoveTimerJobsToExecutableJobs(finalTimerJobs);
});
}
// if all jobs were executed
millisToWait = asyncExecutor.getDefaultTimerJobAcquireWaitTimeInMillis();
int nrOfJobsAcquired = timerJobs.size();View on GitHub (pinned to d6d39ce1c6)
Solutions
- Inspect the chained exception to find why the lock wait failed
- Verify the lock manager's storage (e.g. ACT_RU_ENTITYLINK/lock table or external store) exists and is reachable
- Ensure custom lock managers only throw FlowableException for expected lock contention
- Retry — the runnable deliberately retries the lock on the next acquisition cycle
Example fix
// before
class MyLockManager implements FlowableLockManager { public void acquireLock(...) { throw new RuntimeException("lock busy"); } }
// after
public void acquireLock(...) { if (locked) { throw new FlowableException("lock busy"); } } Defensive patterns
Strategy: try-catch
Validate before calling
// verify lock table reachability before enabling global lock
try (Connection c = dataSource.getConnection(); Statement s = c.createStatement()) { s.executeQuery("SELECT 1 FROM ACT_RU_JOB LIMIT 1"); } Try / catch
try {
lockManager.acquireLock(...);
} catch (FlowableException expectedLockContention) {
// normal: retry next cycle
} catch (RuntimeException e) {
log.warn("lock wait infrastructure failure", e);
} Prevention
- Ensure custom FlowableLockManager throws only FlowableException for contention
- Verify lock storage exists and is shared cluster-wide
- Monitor lock table latency
When it happens
Trigger: Acquiring the global lock (e.g. via the lock manager/command) throws a non-Flowable exception — infrastructure failures, JDBC errors from the lock table, or a custom lock manager raising unexpected exceptions.
Common situations: Lock table missing or unreachable; database outage during lock acquisition; custom FlowableLockManager implementations throwing raw RuntimeExceptions.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- exception during timer job acquisition for engine {}. Except
- exception during timer job move for engine {}. Exception mes
- Optimistic locking exception (using global acquire lock) for
- there must be at least one job entity manager
- Cannot delete
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/9d24ccea11e1dbd0.
Report an issue: GitHub.