apache/dolphinscheduler · error · ServiceException

10141

10141

Error message

The start time must not be the same as the end

What it means

updateSchedule computes DateUtils.differSec(startTime, endTime); a result of 0 means the start and end times are the same (or both null), which would make the schedule window meaningless, so SCHEDULE_START_TIME_END_TIME_SAME is thrown.

Solutions

  1. Set endTime strictly after startTime in the scheduleExpression JSON.
  2. Always populate both startTime and endTime (epoch millis) when updating the expression.
  3. Client-side validate: startTime < endTime before sending.
  4. Use a realistic long-running window, e.g. start=now, end=now+years, for open-ended schedules.

Example fix

// before
{"startTime":1700000000000,"endTime":1700000000000,"crontab":"0 0 12 * * ?"}   // same times

// after
{"startTime":1700000000000,"endTime":1730000000000,"crontab":"0 0 12 * * ?"}   // end after start
Defensive patterns

Strategy: validation

Validate before calling

if (startTime == null || endTime == null || startTime.equals(endTime)) {
    throw new IllegalArgumentException("startTime and endTime must be set and differ");
}

Try / catch

try {
    schedulerService.updateSchedule(loginUser, projectCode, id, scheduleExpression, ...);
} catch (ServiceException e) {
    if (e.getCode() == Status.SCHEDULE_START_TIME_END_TIME_SAME.getCode()) {
        // widen the schedule window or set an explicit endTime
    }
}

Prevention

When it happens

Trigger: Submitting a scheduleExpression whose startTime equals endTime, or where both are null/absent so differSec returns 0.

Common situations: Copy-pasting the same timestamp into both fields; clients defaulting endTime to startTime; forgetting endTime so both are null; unit tests with placeholder timestamps.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/c4f2b69603bb43e0. Report an issue: GitHub.

Appendix: source

Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java:556

                    ReleaseState.ONLINE.getDescp(), schedule.getId());
            throw new ServiceException(Status.SCHEDULE_CRON_ONLINE_FORBID_UPDATE);
        }

        Date now = new Date();

        tenantExistValidator.validate(tenantCode);
        schedule.setTenantCode(tenantCode);

        // updateWorkflowInstance param
        if (!StringUtils.isEmpty(scheduleExpression)) {
            ScheduleParam scheduleParam = JSONUtils.parseObject(scheduleExpression, ScheduleParam.class);
            if (scheduleParam == null) {
                log.warn("Parameter scheduleExpression is invalid, so parse cron error.");
                throw new ServiceException(Status.PARSE_TO_CRON_EXPRESSION_ERROR);
            }
            if (DateUtils.differSec(scheduleParam.getStartTime(), scheduleParam.getEndTime()) == 0) {
                log.warn("The start time must not be the same as the end or time can not be null.");
                throw new ServiceException(Status.SCHEDULE_START_TIME_END_TIME_SAME);
            }
            if (scheduleParam.getStartTime().getTime() > scheduleParam.getEndTime().getTime()) {
                log.warn("The start time must smaller than end time");
                throw new ServiceException(Status.START_TIME_BIGGER_THAN_END_TIME_ERROR);
            }

            schedule.setStartTime(scheduleParam.getStartTime());
            schedule.setEndTime(scheduleParam.getEndTime());
            if (!CronUtils.isValidExpression(scheduleParam.getCrontab())) {
                log.error("Schedule crontab verify failure, crontab:{}.", scheduleParam.getCrontab());
                throw new ServiceException(Status.SCHEDULE_CRON_CHECK_FAILED, scheduleParam.getCrontab());
            }
            schedule.setCrontab(scheduleParam.getCrontab());
            validateMissedFirePolicy(scheduleParam);
            if (scheduleParam.isMissedFirePolicySet() && scheduleParam.getMissedFirePolicy() != null) {
                schedule.setMissedFirePolicy(scheduleParam.getMissedFirePolicy());
            }
            schedule.setTimezoneId(scheduleParam.getTimezoneId());

View on GitHub (pinned to 02eac45a1b)