quarkusio/quarkus · error · java.lang.IllegalArgumentException

Either the 'cron' expression or the 'every' period must be s

Error message

Either the 'cron' expression or the 'every' period must be set: 

What it means

createTrigger() requires one of two scheduling mechanisms on the @Scheduled annotation/config: a 'cron' expression or an 'every' interval period. When neither is set, the scheduler cannot compute any trigger and throws IllegalArgumentException listing the offending @Scheduled method.

Source

Thrown at extensions/scheduler/runtime/src/main/java/io/quarkus/scheduler/runtime/SimpleScheduler.java:377

        String descriptionValue = SchedulerUtils.lookUpPropertyValue(scheduled.description());
        String description = descriptionValue.isEmpty() ? null : descriptionValue;
        if (!scheduled.cron().isEmpty()) {
            String cron = SchedulerUtils.lookUpPropertyValue(scheduled.cron());
            if (SchedulerUtils.isOff(cron)) {
                return Optional.empty();
            }
            return Optional.of(new CronTrigger(id, start, cronParser.parse(cron),
                    SchedulerUtils.parseOverdueGracePeriod(scheduled, defaultGracePeriod),
                    SchedulerUtils.parseCronTimeZone(scheduled), methodDescription, description));
        } else if (!scheduled.every().isEmpty()) {
            final OptionalLong everyMillis = SchedulerUtils.parseEveryAsMillis(scheduled);
            if (everyMillis.isEmpty()) {
                return Optional.empty();
            }
            return Optional.of(new IntervalTrigger(id, start, everyMillis.getAsLong(),
                    SchedulerUtils.parseOverdueGracePeriod(scheduled, defaultGracePeriod), methodDescription, description));
        } else {
            throw new IllegalArgumentException("Either the 'cron' expression or the 'every' period must be set: " + scheduled);
        }
    }

    static class ScheduledTask {

        final boolean isProgrammatic;
        final SimpleTrigger trigger;
        final ScheduledInvoker invoker;

        ScheduledTask(SimpleTrigger trigger, ScheduledInvoker invoker, boolean isProgrammatic) {
            this.trigger = trigger;
            this.invoker = invoker;
            this.isProgrammatic = isProgrammatic;
        }

        void execute(ZonedDateTime now, Vertx vertx) {
            if (!trigger.isRunning()) {
                return;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add a cron expression: @Scheduled(cron = "0 15 10 * * ?") or set quarkus.scheduler.cron-type-compatible config.
  2. Add an interval: @Scheduled(every = "10s") or every = "{property:expression}".
  3. If the value comes from config, verify the property (e.g. app.some.every) resolves to a non-empty duration.
  4. If the schedule should be conditional, guard with @Scheduled(every="0")-style disabled convention or skip scheduling in code rather than leaving both unset.
  5. Programmatic API: call either cron(...) or every(...) on the JobDefinition before schedule().

Example fix

// before
@Scheduled(delayed = "10s")
void run() { ... }
// after
@Scheduled(delayed = "10s", every = "5m")
void run() { ... }
Defensive patterns

Strategy: validation

Validate before calling

Scheduled s = method.getAnnotation(Scheduled.class);
if ((s == null || (s.cron().isEmpty() && s.every().isEmpty()))) {
    throw new IllegalArgumentException("@Scheduled on " + method + " must set cron or every");
}

Try / catch

try {
    trigger = schedulerRuntime.createTrigger(...);
} catch (IllegalArgumentException e) {
    log.error("Schedule misconfigured: set either cron or every", e);
}

Prevention

When it happens

Trigger: A @Scheduled method (or programmatic Schedule config) declares neither cron() nor every() — e.g. @Scheduled with only delayed/overdue settings, or both left blank/empty.

Common situations: Misconfigured @Scheduled annotation where the developer removed cron but forgot every (or vice versa); building a schedule programmatically with a builder that only sets gracePeriod/delay; config property overriding cron/every to an empty string.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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