flowable/flowable-engine · error
exception during resetting expired jobs: {} for engine {}
Error message
exception during resetting expired jobs: {} for engine {} What it means
WARN log from ResetExpiredJobsRunnable when resetting expired (locked) async jobs fails with an exception other than FlowableOptimisticLockingException. Optimistic-lock failures are logged at debug (expected in clusters); anything else stops the reset loop (hasExpiredJobs=false) and the thread sleeps before the next cycle.
Source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/ResetExpiredJobsRunnable.java:131
if (!expiredJobIds.isEmpty()) {
asyncExecutor.getJobServiceConfiguration().getCommandExecutor().execute(
new ResetExpiredJobsCmd(expiredJobIds, jobEntityManager, jobServiceConfiguration));
} else {
hasExpiredJobs = false;
}
} catch (Throwable e) {
// If an optimistic locking exception happens, we continue resetting.
// If another exception happens, we return the method which will trigger a sleep.
if (e instanceof FlowableOptimisticLockingException) {
LOGGER.debug("Optimistic lock exception while resetting locked jobs for engine {}", asyncExecutor.getJobServiceConfiguration().getEngineName(), e);
} else {
LOGGER.warn("exception during resetting expired jobs: {} for engine {}", e.getMessage(),
asyncExecutor.getJobServiceConfiguration().getEngineName(), e);
hasExpiredJobs = false; // will stop the loop
}
}
}
}
public void stop() {
synchronized (MONITOR) {
isInterrupted = true;
if (isWaiting.compareAndSet(true, false)) {
MONITOR.notifyAll();
}
}
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Check the chained exception for the DB-level root cause
- Verify database connectivity and pool health during the reset window
- Confirm ACT_RU_JOB schema (LOCK_OWNER_/LOCK_EXP_TIME_ columns) matches the engine version
- The loop self-recovers on the next cycle; if it recurs, investigate DB load/locks causing deadlocks
Example fix
// before: pool too small under load causing timeouts during reset maximumPoolSize=5 // after maximumPoolSize=20; connectionTimeout=30000
Defensive patterns
Strategy: retry
Validate before calling
// pool health check before engine start
try (Connection c = dataSource.getConnection()) { if (!c.isValid(5)) throw new SQLException("unhealthy connection"); } Try / catch
try {
resetExpiredJobs();
} catch (FlowableOptimisticLockingException e) {
log.debug("expected in cluster", e); // benign
} catch (Throwable e) {
log.warn("reset failed; will retry after sleep", e);
} Prevention
- Size the connection pool for all executor threads
- Keep ACT_RU_JOB schema current
- Treat optimistic-lock resets as normal cluster noise
When it happens
Trigger: Non-optimistic-lock Throwable during the ResetExpiredJobsCmd update of expired jobs: DB connection loss, SQL errors, deadlocks while moving lock ownership of expired jobs.
Common situations: Database failover while the reset thread runs; connection pool exhaustion; schema mismatch of ACT_RU_JOB lock columns after upgrades.
Related errors
- exception for engine {} during async job acquisition: {}
- exception during timer job acquisition for engine {}. Except
- exception during timer job move for engine {}. Exception mes
- 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/87862f2edc479d61.
Report an issue: GitHub.