{"record":{"id":"19e968fd542b2cd7","repo":"quarkusio/quarkus","slug":"either-sync-or-async-task-must-be-set-19e968","errorCode":null,"errorMessage":"Either sync or async task must be set","messagePattern":"Either sync or async task must be set","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/scheduler/runtime/src/main/java/io/quarkus/scheduler/runtime/SimpleScheduler.java","lineNumber":633,"sourceCode":"            return scheduledFireTime.toInstant();\n        }\n\n    }\n\n    public class SimpleJobDefinition extends AbstractJobDefinition<SimpleJobDefinition> {\n\n        private final SchedulerConfig schedulerConfig;\n\n        SimpleJobDefinition(String id, SchedulerConfig schedulerConfig) {\n            super(id);\n            this.schedulerConfig = schedulerConfig;\n        }\n\n        @Override\n        public Trigger schedule() {\n            checkScheduled();\n            if (task == null && asyncTask == null) {\n                throw new IllegalStateException(\"Either sync or async task must be set\");\n            }\n            scheduled = true;\n            ScheduledInvoker invoker;\n            if (task != null) {\n                // Use the default invoker to make sure the CDI request context is activated\n                invoker = new DefaultInvoker() {\n                    @Override\n                    public CompletionStage<Void> invokeBean(ScheduledExecution execution) {\n                        try {\n                            task.accept(execution);\n                            return CompletableFuture.completedStage(null);\n                        } catch (Exception e) {\n                            return CompletableFuture.failedStage(e);\n                        }\n                    }\n\n                    @Override\n                    public boolean isRunningOnVirtualThread() {","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/scheduler/runtime/src/main/java/io/quarkus/scheduler/runtime/SimpleScheduler.java#L615-L651","documentation":"The programmatic JobDefinition built via Scheduler.newJob() must specify what to execute: either a synchronous task (execute(...)) or an async task (setAsyncTask(...)). schedule() validates this and throws IllegalStateException if both are unset — a job with no body can never run.","triggerScenarios":"Calling scheduler.newJob(\"id\").setCron(\"...\")....schedule() without ever invoking execute(task) or setAsyncTask(asyncTask); or setting a task conditionally that ended up null.","commonSituations":"Programmatic job registration built dynamically where the runnable is resolved from DI/config and can be null; refactoring that removed the execute() call; copy-pasted builder code missing the task line.","solutions":["Call execute(runnableOrConsumer) on the JobDefinition before schedule().","For non-blocking work, call setAsyncTask(...) instead.","If the job is conditional, skip the entire newJob(...).schedule() chain when no task exists rather than scheduling an empty job.","Validate the task reference is non-null before building the JobDefinition."],"exampleFix":"// before\nscheduler.newJob(\"cleanup\").setCron(\"0 0 2 * * ?\").schedule();\n// after\nscheduler.newJob(\"cleanup\").setCron(\"0 0 2 * * ?\").execute(cleanupTask).schedule();","handlingStrategy":"validation","validationCode":"Runnable task = resolveTask();\nObjects.requireNonNull(task, \"Job task must not be null before scheduling\");\nscheduler.newJob(\"id\").setCron(\"0 0 2 * * ?\").execute(task).schedule();","typeGuard":null,"tryCatchPattern":"try {\n    definition.schedule();\n} catch (IllegalStateException e) {\n    if (!e.getMessage().contains(\"sync or async task\")) throw e;\n    log.error(\"Job definition has no execute()/setAsyncTask() set\");\n}","preventionTips":["Chain .execute(...) or .setAsyncTask(...) immediately after newJob(...)","Skip creating the definition entirely when no task is available","Unit-test programmatic job registration paths"],"tags":["scheduler","programmatic-api","quarkus"],"backgroundTag":"missing-required-config","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}