flowable/flowable-engine · error · FlowableIllegalArgumentException

At most one non-null value can be provided for timeDate, tim

Error message

At most one non-null value can be provided for timeDate, timeDuration, or timeCycle

What it means

RescheduleTimerJobCmd validates that exactly one of timeDate, timeDuration, or timeCycle is non-null when rescheduling a timer job. It counts the non-null values via Collections.frequency and throws this error when more than one (or, structurally, any count other than 0 or 2 nulls — i.e. more than one non-null) is supplied. The library enforces a single scheduling expression per timer reschedule.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/RescheduleTimerJobCmd.java:47

    private static final long serialVersionUID = 1L;

    private final String timerJobId;
    private String timeDate;
    private String timeDuration;
    private String timeCycle;
    private String endDate;
    private String calendarName;

    public RescheduleTimerJobCmd(String timerJobId, String timeDate, String timeDuration, String timeCycle, String endDate, String calendarName) {
        if (timerJobId == null) {
            throw new FlowableIllegalArgumentException("The timer job id is mandatory, but 'null' has been provided.");
        }

        int timeValues = Collections.frequency(Arrays.asList(timeDate, timeDuration, timeCycle), null);
        if (timeValues == 0) {
            throw new FlowableIllegalArgumentException("A non-null value is required for one of timeDate, timeDuration, or timeCycle");
        } else if (timeValues != 2) {
            throw new FlowableIllegalArgumentException("At most one non-null value can be provided for timeDate, timeDuration, or timeCycle");
        }

        if (endDate != null && timeCycle == null) {
            throw new FlowableIllegalArgumentException("An end date can only be provided when rescheduling a timer using timeDuration.");
        }

        this.timerJobId = timerJobId;
        this.timeDate = timeDate;
        this.timeDuration = timeDuration;
        this.timeCycle = timeCycle;
        this.endDate = endDate;
        this.calendarName = calendarName;
    }

    @Override
    public TimerJobEntity execute(CommandContext commandContext) {
        TimerEventDefinition ted = new TimerEventDefinition();
        ted.setTimeDate(timeDate);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass exactly one of timeDate, timeDuration, or timeCycle; null out the others.
  2. Decide the schedule mode explicitly (fixed date vs duration vs cycle) and use the corresponding reschedule method.
  3. If an end date is needed, use timeDuration (with endDate) — not timeCycle or timeDate.

Example fix

// before
managementService.rescheduleJob(jobId, now, "PT30M", null, "R/PT1H");
// after
managementService.rescheduleTimeDurationJob(jobId, "PT30M", now);
Defensive patterns

Strategy: validation

Validate before calling

int nonNull = (timeDate!=null?1:0)+(timeDuration!=null?1:0)+(timeCycle!=null?1:0);
if (nonNull != 1) throw new IllegalArgumentException("Provide exactly one of timeDate/timeDuration/timeCycle");

Try / catch

try {
    managementService.rescheduleTimeDurationJob(jobId, duration, endDate);
} catch (FlowableIllegalArgumentException e) {
    // handle invalid schedule combination
}

Prevention

When it happens

Trigger: Calling ManagementService.rescheduleTimeDurationJob/rescheduleTimeDateJob-style APIs (or executing RescheduleTimerJobCmd directly) with e.g. both a timeDate Date and a timeDuration String, or timeDuration plus timeCycle, non-null at the same time.

Common situations: Developers migrating code that sets multiple fields 'to be safe'; combining a fixed date with an ISO duration; wiring UI forms that keep previously-filled values when switching schedule modes.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/8501f054326c416f. Report an issue: GitHub.