flowable/flowable-engine · error · FlowableIllegalArgumentException

The timer job id is mandatory, but 'null' has been provided.

Error message

The timer job id is mandatory, but 'null' has been provided.

What it means

RescheduleTimerJobCmd requires a timerJobId to locate the existing timer job, and throws FlowableIllegalArgumentException when the id is null. Without the id the command cannot find which job to reschedule, so it fails immediately in the constructor before any rescheduling logic runs.

Source

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

import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.util.TimerUtil;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;

public class RescheduleTimerJobCmd implements Command<TimerJobEntity>, Serializable {

    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;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Obtain the timer job id from managementService.createTimerJobQuery() (e.g. .timers().list()) and verify it is non-null before rescheduling.
  2. Confirm the timer job still exists (it may have executed or been deleted); re-query for the current id.
  3. Use the correct id type: TimerJob entity ids from the timer job query, not Job/DeadLetterJob ids.

Example fix

// before
managementService.rescheduleTimeCycleJob(null, "0 0/5 * * * ?", null, "UTC", null); // null id
// after
TimerJob timerJob = managementService.createTimerJobQuery().timers().singleResult();
if (timerJob != null) {
    managementService.rescheduleTimeCycleJob(timerJob.getId(), "0 0/5 * * * ?", null, "UTC", null);
}
Defensive patterns

Strategy: validation

Validate before calling

TimerJob job = managementService.createTimerJobQuery().timers().jobId(timerJobId).singleResult();
if (timerJobId == null || job == null) {
    throw new IllegalStateException("Timer job " + timerJobId + " does not exist");
}

Try / catch

try {
    managementService.rescheduleTimeDateJob(timerJobId, newDate);
} catch (FlowableIllegalArgumentException e) {
    // timerJobId was null or invalid; re-query the timer job and retry with a valid id
}

Prevention

When it happens

Trigger: Calling managementService.rescheduleTimeDateJob(null, ...), rescheduleTimeDurationJob(null, ...), rescheduleTimeCycleJob(null, ...), or constructing RescheduleTimerJobCmd directly with timerJobId == null — e.g. the id variable was never populated from managementService.createTimerJobQuery().

Common situations: Fetching the timer job by processInstanceId and assuming exactly one result instead of calling singleResult() safely; the timer job already executed and was removed, so the stored id no longer resolves; passing a job id where a timer job id is required (dead-letter vs timer job tables).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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