{"record":{"id":"bf64f8acd1980a9d","repo":"flowable/flowable-engine","slug":"an-end-date-can-only-be-provided-when-rescheduling","errorCode":null,"errorMessage":"An end date can only be provided when rescheduling a timer using timeDuration.","messagePattern":"An end date can only be provided when rescheduling a timer using timeDuration\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/RescheduleTimerJobCmd.java","lineNumber":51,"sourceCode":"    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;\n        this.calendarName = calendarName;\n    }\n\n    @Override\n    public TimerJobEntity execute(CommandContext commandContext) {\n        TimerEventDefinition ted = new TimerEventDefinition();\n        ted.setTimeDate(timeDate);\n        ted.setTimeDuration(timeDuration);\n        ted.setTimeCycle(timeCycle);\n        ted.setEndDate(endDate);\n        ted.setCalendarName(calendarName);","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/RescheduleTimerJobCmd.java#L33-L69","documentation":"RescheduleTimerJobCmd only permits endDate when the timer is rescheduled with a repeating timeCycle... actually per the check: endDate is only allowed when timeCycle == null — but the message says timeDuration. The command throws when endDate != null while timeCycle is null and the caller did not supply a valid single timeDuration setup; effectively endDate is only meaningful for duration-based timers in this API path. It guards against nonsensical schedule combinations.","triggerScenarios":"Executing RescheduleTimerJobCmd with endDate non-null but timeCycle non-null (endDate + cycle), or endDate non-null with timeDate — any combination where the repeat/end semantics are not duration-driven.","commonSituations":"Developers wanting a timer to stop after a deadline copy the endDate parameter from timer definitions that used ISO 8601 repeat cycles, mixing endDate with timeCycle; or reschedule calls built generically from form data carrying a stale endDate.","solutions":["Remove endDate unless you are rescheduling with timeDuration.","If you need a bounded repeating timer, express it via timeDuration plus endDate as supported by this command.","Null the endDate field when passing timeCycle or timeDate."],"exampleFix":"// before\nnew RescheduleTimerJobCmd(jobId, null, \"PT1H\", \"R/PT1H\", endDate);\n// after\nnew RescheduleTimerJobCmd(jobId, null, \"PT1H\", null, endDate);","handlingStrategy":"validation","validationCode":"if (endDate != null && (timeCycle != null || timeDuration == null)) {\n    throw new IllegalArgumentException(\"endDate only allowed with timeDuration\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    managementService.rescheduleTimeDurationJob(jobId, duration, endDate);\n} catch (FlowableIllegalArgumentException e) {\n    // drop endDate or switch to duration-based schedule\n}","preventionTips":["Only set endDate together with timeDuration","Clear endDate when switching schedule modes","Check API docs for which time field supports end dates"],"tags":["validation","timer","scheduler","illegal-argument"],"backgroundTag":"conflicting-config-options","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}