quarkusio/quarkus · error · IllegalStateException

A task instance cannot be scheduled programmatically if DB s

Error message

A task instance cannot be scheduled programmatically if DB store type is used; register a task class instead

What it means

Same DB-store constraint for tasks: with `store-type=db`, a scheduled job must reference a Task class (reconstructible/serializable), not an inline Consumer instance. `setTask(Consumer, boolean)` throws IllegalStateException when a task instance is given without a task class.

Source

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

        @Override
        public Class<? extends SkipPredicate> skipPredicateClass() {
            return skipPredicateClass;
        }

        @Override
        public QuartzJobDefinition setSkipPredicate(SkipPredicate skipPredicate) {
            if (storeType.isDbStore() && skipPredicateClass == null) {
                throw new IllegalStateException(
                        "A skip predicate instance cannot be scheduled programmatically if DB store type is used; register a skip predicate class instead");
            }
            return super.setSkipPredicate(skipPredicate);
        }

        @Override
        public QuartzJobDefinition setTask(Consumer<ScheduledExecution> task, boolean runOnVirtualThread) {
            if (storeType.isDbStore() && taskClass == null) {
                throw new IllegalStateException(
                        "A task instance cannot be scheduled programmatically if DB store type is used; register a task class instead");
            }
            return super.setTask(task, runOnVirtualThread);
        }

        @Override
        public QuartzJobDefinition setAsyncTask(Function<ScheduledExecution, Uni<Void>> asyncTask) {
            if (storeType.isDbStore() && asyncTaskClass == null) {
                throw new IllegalStateException(
                        "An async task instance cannot be scheduled programmatically if DB store type is used; register an async task class instead");
            }
            return super.setAsyncTask(asyncTask);
        }

        @Override
        public Trigger schedule() {
            checkScheduled();
            if (task == null && asyncTask == null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Define `class MyJob implements Consumer<ScheduledExecution>` and call `setTaskClass(MyJob.class)` instead of passing an instance
  2. Use `quarkus.quartz.store-type=memory` if DB persistence is unnecessary
  3. Keep an instance-free path: register the task class as a bean so Quartz can recreate it after restart

Example fix

// before
job.setTask(this::sendReport, false);
// after
job.setTaskClass(SendReportTask.class); // implements Consumer<ScheduledExecution>
Defensive patterns

Strategy: validation

Validate before calling

if (quarkusQuartzConfig.storeType().isDbStore()) {
    job.setTaskClass(MyTask.class);
} else {
    job.setTask(this::execute, false);
}

Prevention

When it happens

Trigger: Calling `quartzJobDefinition.setTask(exec -> doWork(), false)` (or with a non-virtual-thread flag) while `store-type=db` and `setTaskClass` was not invoked.

Common situations: Works in dev/memory store, breaks with JDBC store; passing a method reference or lambda to setTask in production config.

Related errors


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