quarkusio/quarkus · error · IllegalStateException
SchedulerException while scheduling job (no message)
Error message
SchedulerException while scheduling job (no message)
What it means
When a scheduled job definition is registered programmatically, QuartzSchedulerImpl calls scheduler.scheduleJob(jobDetail, trigger) (or reschedules). If the underlying Quartz Scheduler throws a SchedulerException — e.g. the scheduler is not started/shut down, the JobDetail/Trigger pair is invalid, or the job store rejected the operation — it is wrapped in an IllegalStateException and rethrown to the caller of the public scheduling API.
Source
Thrown at extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzSchedulerImpl.java:1063
}, invoker,
SchedulerUtils.parseOverdueGracePeriod(scheduled, defaultOverdueGracePeriod),
runtimeConfig.runBlockingScheduledMethodOnQuartzThread(), true, null, description);
QuartzTrigger existing = scheduledTasks.putIfAbsent(scheduled.identity(), quartzTrigger);
if (existing != null) {
throw new IllegalStateException("A job with this identity is already scheduled: " + scheduled.identity());
}
try {
if (oldTrigger != null) {
scheduler.rescheduleJob(trigger.getKey(), trigger);
LOGGER.debugf("Rescheduled job definition with config %s", scheduled);
} else {
scheduler.scheduleJob(jobDetail, trigger);
LOGGER.debugf("Scheduled job definition with config %s", scheduled);
}
} catch (SchedulerException e) {
throw new IllegalStateException(e);
}
return quartzTrigger;
}
/**
* @see Nonconcurrent
*/
@DisallowConcurrentExecution
static class NonconcurrentInvokerJob extends InvokerJob {
NonconcurrentInvokerJob(QuartzTrigger trigger, Vertx vertx) {
super(trigger, vertx);
}
@Override
boolean awaitResult() {
return true;
}View on GitHub (pinned to e1c734241f)
Solutions
- Check the wrapped SchedulerException's message/cause (IllegalStateException.getCause()) for the real Quartz failure reason
- Verify the job store configuration (quarkus.quartz.store-type); for jdbc-store confirm the datasource is configured and reachable at startup
- Ensure you do not schedule jobs manually while the Quarkus scheduler is shut down or still starting
- If rescheduling, make sure the job identity and trigger definition match what is stored, or delete the job first
- Fix any earlier startup failure that caused the scheduler to stop before this job was registered
Example fix
// before
scheduler.scheduleJob(jobDetail, trigger); // throws IllegalStateException wrapping SchedulerException
// after
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (IllegalStateException e) {
LOG.errorf(e.getCause(), "Failed to schedule job %s", jobDetail.getKey());
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before scheduling, verify the scheduler is not shutdown and the job key is free
Scheduler s = ...; // obtained from the running Quartz scheduler
if (s.isShutdown()) { throw new IllegalStateException("Scheduler already stopped"); }
if (s.checkExists(jobKey)) { s.deleteJob(jobKey); } Try / catch
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (IllegalStateException e) {
// cause is the SchedulerException
Throwable cause = e.getCause();
LOG.errorf(cause, "Quartz rejected scheduling of %s", jobDetail.getKey());
} Prevention
- Never schedule after application shutdown begins
- Use unique job identities and delete before re-registering
- Validate cron expressions before building triggers
- Keep JDBC job store datasources available during startup
When it happens
Trigger: Calling QuartzSchedulerImpl.scheduleJob (or rescheduling an existing job definition) when the Quartz scheduler rejects the JobDetail/Trigger: scheduler already shut down, duplicate job key with incompatible trigger, or a persistent job store (JDBC) failing to persist the job.
Common situations: Registering jobs during startup after the scheduler stopped due to another startup failure; JDBC job store whose datasource is down or misconfigured; scheduling two jobs with the same identity but conflicting settings; live-reload reconfiguration racing a scheduler shutdown.
Related errors
- Job ${beanClass} can not be interrupted, since it does not i
- Dev services for ${request.getName()} requires a startable s
- This cache is not an instance of
- Could not initialize mapped class ${className}
- No template variant found
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ed387e19a6f48acb.
Report an issue: GitHub.