{"record":{"id":"b0a93cea2eefa6ac","repo":"flowable/flowable-engine","slug":"the-timer-job-id-is-mandatory-but-null-has-been","errorCode":null,"errorMessage":"The timer job id is mandatory, but 'null' has been provided.","messagePattern":"The timer job id is mandatory, but 'null' has been provided\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/RescheduleTimerJobCmd.java","lineNumber":40,"sourceCode":"import org.flowable.common.engine.impl.interceptor.Command;\nimport org.flowable.common.engine.impl.interceptor.CommandContext;\nimport org.flowable.engine.impl.util.TimerUtil;\nimport org.flowable.job.service.impl.persistence.entity.TimerJobEntity;\n\npublic class RescheduleTimerJobCmd implements Command<TimerJobEntity>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private final String timerJobId;\n    private String timeDate;\n    private String timeDuration;\n    private String timeCycle;\n    private String endDate;\n    private String calendarName;\n\n    public RescheduleTimerJobCmd(String timerJobId, String timeDate, String timeDuration, String timeCycle, String endDate, String calendarName) {\n        if (timerJobId == null) {\n            throw new FlowableIllegalArgumentException(\"The timer job id is mandatory, but 'null' has been provided.\");\n        }\n\n        int timeValues = Collections.frequency(Arrays.asList(timeDate, timeDuration, timeCycle), null);\n        if (timeValues == 0) {\n            throw new FlowableIllegalArgumentException(\"A non-null value is required for one of timeDate, timeDuration, or timeCycle\");\n        } else if (timeValues != 2) {\n            throw new FlowableIllegalArgumentException(\"At most one non-null value can be provided for timeDate, timeDuration, or timeCycle\");\n        }\n\n        if (endDate != null && timeCycle == null) {\n            throw new FlowableIllegalArgumentException(\"An end date can only be provided when rescheduling a timer using timeDuration.\");\n        }\n\n        this.timerJobId = timerJobId;\n        this.timeDate = timeDate;\n        this.timeDuration = timeDuration;\n        this.timeCycle = timeCycle;\n        this.endDate = endDate;","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/RescheduleTimerJobCmd.java#L22-L58","documentation":"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.","triggerScenarios":"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().","commonSituations":"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).","solutions":["Obtain the timer job id from managementService.createTimerJobQuery() (e.g. .timers().list()) and verify it is non-null before rescheduling.","Confirm the timer job still exists (it may have executed or been deleted); re-query for the current id.","Use the correct id type: TimerJob entity ids from the timer job query, not Job/DeadLetterJob ids."],"exampleFix":"// before\nmanagementService.rescheduleTimeCycleJob(null, \"0 0/5 * * * ?\", null, \"UTC\", null); // null id\n// after\nTimerJob timerJob = managementService.createTimerJobQuery().timers().singleResult();\nif (timerJob != null) {\n    managementService.rescheduleTimeCycleJob(timerJob.getId(), \"0 0/5 * * * ?\", null, \"UTC\", null);\n}","handlingStrategy":"validation","validationCode":"TimerJob job = managementService.createTimerJobQuery().timers().jobId(timerJobId).singleResult();\nif (timerJobId == null || job == null) {\n    throw new IllegalStateException(\"Timer job \" + timerJobId + \" does not exist\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    managementService.rescheduleTimeDateJob(timerJobId, newDate);\n} catch (FlowableIllegalArgumentException e) {\n    // timerJobId was null or invalid; re-query the timer job and retry with a valid id\n}","preventionTips":["Always source the id from managementService.createTimerJobQuery() rather than a cached or hand-entered value.","Use singleResult() checks before rescheduling to confirm the job still exists.","Never pass a Job or DeadLetterJob id where a TimerJob id is required."],"tags":["flowable","timer-job","null-argument","reschedule"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}