flowable/flowable-engine · error
exception for engine {} during async job acquisition: {}
Error message
exception for engine {} during async job acquisition: {} What it means
Generic WARN log from the async job acquisition thread: any Throwable thrown during acquireAndExecuteJobs that is not an optimistic-locking exception is caught and logged here with the engine name and message. It signals the acquisition cycle failed (e.g. DB error) and the thread will sleep before retrying.
Source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/AcquireAsyncJobsDueRunnable.java:220
} catch (FlowableOptimisticLockingException optimisticLockingException) {
lifecycleListener.optimistLockingException(getEngineName(), asyncExecutor.getMaxAsyncJobsDuePerAcquisition());
if (globalAcquireLockEnabled) {
LOGGER.warn("Optimistic locking exception (using global acquire lock) for engine {}", getEngineName(), optimisticLockingException);
} else {
LOGGER.debug(
"Optimistic locking exception during async job acquisition. If you have multiple async executors running against the same database, " +
"this exception means that this thread tried to acquire a due async job, which already was acquired by another " +
"async executor acquisition thread.This is expected behavior in a clustered environment. " +
"You can ignore this message if you indeed have multiple async executor acquisition threads running against the same database. " +
"For engine {}. Exception message: {}",
getEngineName(), optimisticLockingException.getMessage());
}
} catch (Throwable e) {
LOGGER.warn("exception for engine {} during async job acquisition: {}", getEngineName(), e.getMessage(), e);
}
return asyncExecutor.getDefaultAsyncJobAcquireWaitTimeInMillis();
}
protected List<JobInfoEntity> offerJobs(List<? extends JobInfoEntity> acquiredJobs) {
List<JobInfoEntity> rejected = new ArrayList<>();
for (JobInfoEntity job : acquiredJobs) {
boolean jobSuccessFullyOffered = asyncExecutor.executeAsyncJob(job);
if (!jobSuccessFullyOffered) {
rejected.add(job);
}
}
return rejected;
}
public void stop() {
synchronized (MONITOR) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Read the chained stack trace in the log to identify the root cause (usually a SQL/DB error)
- Verify database connectivity and connection pool health
- Check that the ACT_RU_JOB schema matches your Flowable version (run the DB upgrade scripts)
- If persistent, inspect the failing command/query and any custom session factories
Example fix
// before: acquisition thread repeatedly fails on dead pool connections
// after: validate connections and cap retries
dataSource.setDefaultTestOnBorrow(true);
// e.g. Hikari: hikariConfig.setConnectionTestQuery("SELECT 1"); Defensive patterns
Strategy: try-catch
Validate before calling
// health-check DB before starting the engine
try (Connection c = dataSource.getConnection()) { c.isValid(5); } catch (SQLException e) { fail("database unreachable"); } Try / catch
try {
executor.start();
} catch (DataAccessException | SQLException e) {
log.error("job acquisition failed due to DB issue", e);
// alert / backoff / retry cycle
} Prevention
- Monitor database connectivity and pool saturation
- Keep schema in sync with Flowable version via upgrade scripts
- Add alerts on repeated acquisition-failure log lines
- Use validated/test-on-borrow pooled connections
When it happens
Trigger: Any non-optimistic-lock Throwable during job acquisition: database connectivity loss, SQL errors, deadlock, command execution failure inside AcquireAsyncJobsDueCmd.
Common situations: Transient DB outages or failovers in clustered environments; connection pool exhaustion; schema mismatch after a Flowable version upgrade (missing job tables/columns).
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
- Optimistic locking exception (using global acquire lock) for
- exception during timer job move for engine {}. Exception mes
- exception during resetting expired jobs: {} for engine {}
- There are app definitions with key = '' and version = ''
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/08246c873280414f.
Report an issue: GitHub.