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

  1. Check the chained exception for the DB-level root cause
  2. Verify database connectivity and pool health during the reset window
  3. Confirm ACT_RU_JOB schema (LOCK_OWNER_/LOCK_EXP_TIME_ columns) matches the engine version
  4. 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

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


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