quarkusio/quarkus · error · IllegalStateException

Sync task was already set

Error message

Sync task was already set

What it means

AbstractJobDefinition.setAsyncTask() installs the async Uni-returning task for a job definition. Because a job may define only one task, this IllegalStateException is thrown when a synchronous task (setTask) was already set. It is the mirror guard of 'Async task was already set'.

Source

Thrown at extensions/scheduler/common/src/main/java/io/quarkus/scheduler/common/runtime/AbstractJobDefinition.java:138

        if (asyncTask != null) {
            throw new IllegalStateException("Async task was already set");
        }
        this.task = Objects.requireNonNull(task);
        this.runOnVirtualThread = runOnVirtualThread;
        return self();
    }

    @Override
    public THIS setTask(Class<? extends Consumer<ScheduledExecution>> taskClass, boolean runOnVirtualThread) {
        this.taskClass = Objects.requireNonNull(taskClass);
        return setTask(SchedulerUtils.instantiateBeanOrClass(taskClass), runOnVirtualThread);
    }

    @Override
    public THIS setAsyncTask(Function<ScheduledExecution, Uni<Void>> asyncTask) {
        checkScheduled();
        if (task != null) {
            throw new IllegalStateException("Sync task was already set");
        }
        this.asyncTask = Objects.requireNonNull(asyncTask);
        return self();
    }

    @Override
    public THIS setAsyncTask(Class<? extends Function<ScheduledExecution, Uni<Void>>> asyncTaskClass) {
        this.asyncTaskClass = Objects.requireNonNull(asyncTaskClass);
        return setAsyncTask(SchedulerUtils.instantiateBeanOrClass(asyncTaskClass));
    }

    protected void checkScheduled() {
        if (scheduled) {
            throw new IllegalStateException("Cannot modify a job that was already scheduled");
        }
    }

    @SuppressWarnings("unchecked")

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the redundant setTask call so only setAsyncTask remains
  2. Pick one execution style per job definition
  3. Instantiate a new JobDefinition if you need a differently configured job
  4. Search the builder chain for both setters and delete the obsolete one

Example fix

// before
scheduler.newJob("j").setTask(c).setAsyncTask(fn);
// after
scheduler.newJob("j").setAsyncTask(fn);
Defensive patterns

Strategy: validation

Validate before calling

if (syncTaskSet) {
    throw new IllegalStateException("task already set; remove setTask before setAsyncTask");
}
definition.setAsyncTask(fn);

Try / catch

try {
    definition.setAsyncTask(fn);
} catch (IllegalStateException e) {
    LOG.error("Job {} already has a sync task", name, e);
}

Prevention

When it happens

Trigger: Calling scheduler.newJob(...).setTask(consumer).setAsyncTask(fn) on the same definition; calling setAsyncTask(Class) overloads after setTask; reuse of a JobDefinition that already carries a sync task.

Common situations: Migrating a job from sync to async execution while keeping the old setTask call; framework wrappers that pre-set a sync task; accidental double-configuration in fluent chains.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/bbbdb287c88cb8bb. Report an issue: GitHub.