quarkusio/quarkus · warning · RuntimeException

java.util.concurrent.ExecutionException wrapped SchedulerExc

Error message

java.util.concurrent.ExecutionException wrapped SchedulerException from scheduler.shutdown(true)

What it means

During graceful shutdown with a non-zero quarkus.quartz.shutdown-wait-time, Quarkus calls scheduler.shutdown(true) in a CompletableFuture and wraps any SchedulerException from it in a RuntimeException inside the async supplier. The outer future then fails with a TimeoutException on expiry or an ExecutionException wrapping this RuntimeException. This exception is caught by destroy() and only logged as a warning — the application still shuts down.

Source

Thrown at extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzSchedulerImpl.java:550

     * Need to gracefully shut down the scheduler making sure that all triggers have been
     * released before datasource shutdown.
     *
     * @param event ignored
     */
    void destroy(@Observes(notifyObserver = Reception.IF_EXISTS) @BeforeDestroyed(ApplicationScoped.class) Object event) {
        if (scheduler != null) {
            try {
                if (shutdownWaitTime.isZero()) {
                    scheduler.shutdown(false);
                } else {
                    CompletableFuture.supplyAsync(new Supplier<>() {
                        @Override
                        public Void get() {
                            // Note that this method does not return until all currently executing jobs have completed
                            try {
                                scheduler.shutdown(true);
                            } catch (SchedulerException e) {
                                throw new RuntimeException(e);
                            }
                            return null;
                        }
                    }).get(shutdownWaitTime.toMillis(), TimeUnit.MILLISECONDS);
                }

            } catch (Exception e) {
                LOGGER.warnf("Unable to gracefully shutdown the scheduler", e);
            }
        }
    }

    @PreDestroy
    void destroy() {
        if (scheduler != null) {
            try {
                if (!scheduler.isShutdown()) {
                    scheduler.shutdown(false); // force shutdown

View on GitHub (pinned to e1c734241f)

Solutions

  1. Increase quarkus.quartz.shutdown-wait-time to exceed the longest job duration
  2. Make jobs interruptible/cooperative so shutdown(true) completes quickly
  3. Ensure the datasource remains available until scheduler shutdown completes (Quarkus handles ordering, but verify custom ordering)
  4. Treat this log warning as non-fatal; set shutdown-wait-time to 0 (PT0S) to skip graceful wait and force shutdown

Example fix

// before (application.properties)
quarkus.quartz.shutdown-wait-time=5S
// after
quarkus.quartz.shutdown-wait-time=60S  # longer than the slowest job
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure jobs finish before shutdown-wait-time expires
Duration longestJob = measureLongestJob();
assert shutdownWaitTime.compareTo(longestJob) > 0;

Try / catch

// Quarkus logs this as a warning in destroy(); no user catch needed.
// For custom shutdown code:
try {
    future.get(waitMillis, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
    LOGGER.warn("Graceful quartz shutdown timed out; jobs may still be running");
} catch (ExecutionException e) {
    LOGGER.warnf(e.getCause(), "Quartz graceful shutdown failed");
}

Prevention

When it happens

Trigger: Application shutdown with shutdown-wait-time > 0 while scheduler.shutdown(true) (wait for running jobs to complete) throws SchedulerException — e.g. JobStore error while waiting on JDBC store, or the shutdown interrupted by store failure.

Common situations: Long-running jobs exceeding shutdown-wait-time (TimeoutException path); JDBC store failing during shutdown; DB already torn down before the scheduler's graceful shutdown runs.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/e35e24f143597110. Report an issue: GitHub.