quarkusio/quarkus · error · IllegalStateException
A skip predicate instance cannot be scheduled programmatical
Error message
A skip predicate instance cannot be scheduled programmatically if DB store type is used; register a skip predicate class instead
What it means
With `quarkus.quartz.store-type=db`, job definitions are persisted to the database and must be reconstructible by class name. A lambda/instance SkipPredicate cannot be serialized, so `setSkipPredicate(SkipPredicate)` rejects instances and demands a registered SkipPredicate class.
Source
Thrown at extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzSchedulerImpl.java:878
@Override
public Class<? extends Consumer<ScheduledExecution>> taskClass() {
return taskClass;
}
@Override
public Class<? extends Function<ScheduledExecution, Uni<Void>>> asyncTaskClass() {
return asyncTaskClass;
}
@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(View on GitHub (pinned to e1c734241f)
Solutions
- Implement SkipPredicate in a named CDI bean/class and register it via `setSkipPredicateClass(MySkipPredicate.class)` before scheduling
- Switch store type to memory if persistence is not needed (`quarkus.quartz.store-type=memory`)
- Instantiate the predicate with a no-arg constructor-capable class and pass the class, not an instance
Example fix
// before job.setSkipPredicate(ctx -> isHoliday(ctx.getScheduledFireTime())); // after job.setSkipPredicateClass(HolidaySkipPredicate.class); // implements SkipPredicate
Defensive patterns
Strategy: validation
Validate before calling
if (quarkusQuartzConfig.storeType().isDbStore()) {
job.setSkipPredicateClass(MySkipPredicate.class);
} else {
job.setSkipPredicate(ctx -> check(ctx));
} Prevention
- Gate programmatic job building on store type
- Prefer class-based predicates everywhere for consistency across environments
- Document store-type assumptions next to job definitions
When it happens
Trigger: Calling `quartzJobDefinition.setSkipPredicate(someLambdaOrInstance)` while the scheduler's store type is DB and `setSkipPredicateClass` was not called first.
Common situations: Local tests with in-memory store work but the app fails in prod with DB store; using a lambda `s -> shouldSkip(s)` for skip logic.
Related errors
- A task instance cannot be scheduled programmatically if DB s
- An async task instance cannot be scheduled programmatically
- Job [{identity}] that was previously scheduled programmatica
- SchedulerException while getting trigger (no message)
- Failed to record call to method ${call.method}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/c07b6e92a16e78ac.
Report an issue: GitHub.