{"record":{"id":"5af952c2740930f6","repo":"quarkusio/quarkus","slug":"job-identity-that-was-previously-scheduled-pro","errorCode":null,"errorMessage":"Job [{identity}] that was previously scheduled programmatically cannot be disabled","messagePattern":"Job \\[(.+?)\\] that was previously scheduled programmatically cannot be disabled","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzSchedulerImpl.java","lineNumber":1021,"sourceCode":"                jobBuilder.usingJobData(EXECUTION_METADATA_SKIP_PREDICATE_CLASS,\n                        executionMetadata.skipPredicateClass().getName());\n            }\n        }\n\n        JobDetail jobDetail = jobBuilder.requestRecovery().build();\n\n        org.quartz.Trigger trigger;\n        Optional<TriggerBuilder<?>> triggerBuilder = createTrigger(scheduled.identity(), scheduled, runtimeConfig,\n                jobDetail, description);\n        if (triggerBuilder.isPresent()) {\n            if (oldTrigger != null) {\n                trigger = triggerBuilder.get().startAt(oldTrigger.getNextFireTime()).build();\n            } else {\n                trigger = triggerBuilder.get().build();\n            }\n        } else {\n            if (oldTrigger != null) {\n                throw new IllegalStateException(\n                        \"Job [\" + scheduled.identity() + \"] that was previously scheduled programmatically cannot be disabled\");\n            }\n            // Job is disabled\n            return null;\n        }\n\n        JobInstrumenter instrumenter = null;\n        if (schedulerConfig.tracingEnabled() && jobInstrumenter.isResolvable()) {\n            instrumenter = jobInstrumenter.get();\n        }\n        invoker = initInvoker(invoker, events, scheduled.concurrentExecution(), skipPredicate, instrumenter,\n                vertx, task != null && runtimeConfig.runBlockingScheduledMethodOnQuartzThread(),\n                SchedulerUtils.parseExecutionMaxDelayAsMillis(scheduled), blockingExecutor);\n        QuartzTrigger quartzTrigger = new QuartzTrigger(trigger.getKey(),\n                new Function<>() {\n                    @Override\n                    public org.quartz.Trigger apply(TriggerKey triggerKey) {\n                        try {","sourceCodeStart":1003,"sourceCodeEnd":1039,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzSchedulerImpl.java#L1003-L1039","documentation":"When a scheduled application's job is disabled (@Scheduled{enabled=false} or equivalent) but a trigger for the same identity already exists in the Quartz store from a previous programmatic schedule, the scheduler cannot reconcile: it refuses to silently disable a job previously scheduled programmatically and throws IllegalStateException.","triggerScenarios":"Disabling a job (e.g. `quarkus.scheduler.enabled=false` per-job config or property-driven enabled=false) while the DB/job-store still holds a trigger with that identity created earlier by programmatic scheduling.","commonSituations":"Toggling a job off via config between deploys with a JDBC store; a job previously registered at runtime then disabled in code; stale triggers left in the DB after refactoring.","solutions":["Delete the stale trigger/job from the Quartz store (scheduler.deleteJob) or clean the QRTZ_ tables for that identity before disabling","Re-enable the job and remove it programmatically (unschedule) instead of using the disabled flag","Rename the job identity so the disabled definition no longer collides with the stored trigger"],"exampleFix":"// before: disabled job with stale trigger\n@Scheduled(identity=\"reports\", disabled=true) ...\n// after: unschedule programmatically instead\nscheduler.unscheduleJob(\"reports\");","handlingStrategy":"try-catch","validationCode":"// check for an existing stored trigger before relying on disabled config\norg.quartz.Trigger existing = scheduler.getTrigger(new TriggerKey(identity, Scheduler.class.getName()));\nboolean safeToDisable = existing == null;","typeGuard":null,"tryCatchPattern":"try {\n    schedulerInstance.schedule(...);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"cannot be disabled\")) { scheduler.deleteJob(jobKey); }\n}","preventionTips":["Unschedule jobs programmatically instead of toggling enabled=false when the store persists triggers","Clean stale QRTZ_ rows when renaming/removing jobs","Keep identity values stable between deploys"],"tags":["quarkus","quartz","state-conflict","db-store"],"backgroundTag":"job-already-scheduled-conflict","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}