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

The async executor's AcquireAsyncJobsDueRunnable logs this warning when waitForLockRunAndRelease (global acquire locking) throws while trying to acquire the engine's global acquire lock. FlowableException subclasses are deliberately not logged because they represent regular lock contention logic; any other exception indicates an unexpected problem (DB connection failure, timeout, etc.) during the lock wait. The runnable swallows the error and retries on the next cycle.

Source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/AcquireAsyncJobsDueRunnable.java:123

        LOGGER.info("starting to acquire async jobs due for engine {}", getEngineName());
        Thread.currentThread().setName(name);

        final CommandExecutor commandExecutor = asyncExecutor.getJobServiceConfiguration().getCommandExecutor();

        long millisToWait = 0L;
        while (!isInterrupted) {

            if (configuration.isGlobalAcquireLockEnabled()) {

                try {
                    millisToWait = lockManager.waitForLockRunAndRelease(configuration.getLockWaitTime(), () -> executeAcquireCycle(commandExecutor));
                } catch (Exception e) {
                    // Don't do anything, lock will be tried again next time
                    millisToWait = asyncExecutor.getDefaultAsyncJobAcquireWaitTimeInMillis();

                    if (!(e instanceof FlowableException)) { // FlowableExeption doesn't need to be logged, could be regular lock logic
                        LOGGER.warn("Error while waiting for global acquire lock for engine {}", getEngineName(), e);
                    }
                }

                if (millisToWait == 0) {
                    // Always wait when running with global acquire lock, to let other nodes have the ability to fill the queue
                    // If 0 was returned, it means there is still work to do, but we want to give other nodes a chance.
                    millisToWait = configuration.getLockPollRate().toMillis();
                }

            } else {
                millisToWait = executeAcquireCycle(commandExecutor);

            }

            if (millisToWait > 0) {
                sleep(millisToWait);
            }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Inspect the attached stack trace for the underlying cause (SQL/connection error) and fix database connectivity or schema issues first.
  2. If caused by lock contention/timeout, tune the async executor's lockWaitTime and acquire wait times so nodes compete less aggressively.
  3. Verify all nodes run compatible Flowable versions sharing the same database, since the global lock is implemented via a shared property row.
  4. If errors recur persistently, check DB health (locks, deadlocks, connection pool exhaustion) and increase pool sizing.
  5. This is a recoverable warning — the executor retries automatically; no code change is needed for transient occurrences.
Defensive patterns

Strategy: retry

Validate before calling

// Before enabling global acquire lock, verify database access
try (Connection c = dataSource.getConnection()) {
    if (!c.isValid(5)) throw new SQLException("DB connection invalid");
}

Try / catch

try {
    millisToWait = lockManager.waitForLockRunAndRelease(lockWaitTime, acquireCycle);
} catch (Exception e) {
    if (!(e instanceof FlowableException)) {
        log.warn("Error while waiting for global acquire lock for engine {}", engineName, e);
    }
    millisToWait = defaultAsyncJobAcquireWaitTimeInMillis; // retry on next cycle
}

Prevention

When it happens

Trigger: In the runnable's run() loop, waitForLockRunAndRelease throws a non-FlowableException while waiting for/releasing the global async job acquire lock — commonly due to database connectivity issues, lock timeouts, or transaction errors against the shared ACT_GE_PROPERTY-based lock row.

Common situations: Multi-node async executor setups where a node loses its DB connection mid-acquire; database deadlock/timeout on the lock table; network blip between the executor and the database; misconfigured lockWaitTime causing repeated failed lock attempts.

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


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