quarkusio/quarkus · error · IllegalStateException
Unable to obtain the job detail for ${triggerKey}
Error message
Unable to obtain the job detail for ${triggerKey} What it means
On startup with a persistent Quartz store, QuartzSchedulerImpl re-schedules synthetic @Scheduled triggers by looking up each stored trigger's JobDetail via scheduler.getJobDetail(). If the JobDetail is missing (null) while a trigger exists, IllegalStateException 'Unable to obtain the job detail for <triggerKey>' is thrown — the scheduler store is inconsistent.
Source
Thrown at extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzSchedulerImpl.java:289
SchedulerUtils.parseOverdueGracePeriod(scheduled, defaultOverdueGracePeriod),
quartzSupport.getRuntimeConfig().runBlockingScheduledMethodOnQuartzThread(), false,
method.getMethodDescription(), description));
} else {
// The job is disabled
scheduler.deleteJob(new JobKey(identity, Scheduler.class.getName()));
}
}
}
// Find persistent jobs scheduled with JobDefinition
if (storeType.isDbStore()) {
Set<TriggerKey> triggers = scheduler
.getTriggerKeys(GroupMatcher.triggerGroupEquals(Scheduler.class.getName()));
for (TriggerKey triggerKey : triggers) {
JobDetail jobDetail = scheduler.getJobDetail(new JobKey(triggerKey.getName(), triggerKey.getGroup()));
if (jobDetail == null) {
throw new IllegalStateException("Unable to obtain the job detail for " + triggerKey);
}
String scheduledJson = jobDetail.getJobDataMap().getString(SCHEDULED_METADATA);
if (scheduledJson != null) {
SyntheticScheduled scheduled = SyntheticScheduled.fromJson(scheduledJson);
org.quartz.Trigger oldTrigger = scheduler.getTrigger(triggerKey);
if (oldTrigger == null) {
throw new IllegalStateException("Unable to obtain the trigger for " + triggerKey);
}
createJobDefinitionQuartzTrigger(new SerializedExecutionMetadata(jobDetail), scheduled, oldTrigger);
}
}
}
if (transaction != null) {
transaction.commit();
}
} catch (Throwable e) {View on GitHub (pinned to e1c734241f)
Solutions
- Clean the orphaned trigger rows: delete the trigger (or the scheduler group) from the Quartz tables, or wipe Quartz tables and let Quarkus re-schedule.
- Ensure all application instances sharing the store use the same quarkus.quartz.scheduler-name and compatible versions.
- Restore schema consistency from backup or re-create the store schema.
- Check for other clients (scripts, other schedulers) mutating the Quartz tables.
Example fix
-- remove orphaned triggers so Quarkus re-creates them DELETE FROM QRTZ_TRIGGERS WHERE SCHED_NAME = 'quarkusQuartzScheduler'; DELETE FROM QRTZ_CRON_TRIGGERS WHERE SCHED_NAME = 'quarkusQuartzScheduler';
Defensive patterns
Strategy: validation
Validate before calling
// startup health check on a JDBC store: every trigger must have a job detail
for (TriggerKey key : scheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(Scheduler.class.getName()))) {
if (scheduler.getJobDetail(new JobKey(key.getName(), key.getGroup())) == null) {
log.error("Orphaned trigger in Quartz store: " + key + " — clean QRTZ_TRIGGERS or reset the store");
}
} Try / catch
try {
scheduler.start();
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Unable to obtain the job detail")) {
// inconsistent store: clean Quartz tables and restart
throw new RuntimeException("Quartz store inconsistent — purge orphaned triggers", e);
}
throw e;
} Prevention
- Never manually delete rows from QRTZ_JOB_DETAILS without cleaning QRTZ_TRIGGERS.
- Use one logical scheduler name per shared store; coordinate multi-app setups.
- Take a DB backup before upgrading Quarkus/Quartz against a persistent store.
When it happens
Trigger: Trigger rows exist in the JDBC (or other persistent) QRTZ_TRIGGERS table but corresponding QRTZ_JOB_DETAILS rows are missing/corrupted — e.g. jobs were removed from another scheduler instance sharing the store, manual DB cleanup, or interrupted schema changes.
Common situations: Multiple apps sharing one Quartz JDBC store with the same scheduler name; manual truncation of QRTZ_JOB_DETAILS; upgrading while old triggers persist; store corruption after crash.
Related errors
- Unable to obtain the trigger for ${triggerKey}
- Unable to create Scheduler
- Custom JDBC delegate implementation class '%s' was not found
- Custom JDBC delegate implementation with name '%s' needs to
- JDBC Store configured but the '%s' datasource is not configu
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4fb3efb9a4ed1b5d.
Report an issue: GitHub.