apache/dolphinscheduler · error · ServiceException

SCHEDULE_CRON_ONLINE_FORBID_UPDATE

SCHEDULE_CRON_ONLINE_FORBID_UPDATE

Error message

Schedule can not be updated due to schedule is {}, scheduleId:{}.

What it means

Thrown by the private SchedulerServiceImpl.updateSchedule when the target schedule's release state is ONLINE. Online schedules are being enforced by the scheduler, so edits are forbidden until they are taken offline.

Source

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

    }

    private void checkScheduleBelongsToProject(Schedule schedule, long projectCode) {
        if (schedule == null) {
            return;
        }
        WorkflowDefinition workflowDefinition =
                workflowDefinitionDao.queryByCode(schedule.getWorkflowDefinitionCode()).orElse(null);
        if (workflowDefinition == null || workflowDefinition.getProjectCode() != projectCode) {
            throw new ServiceException(Status.SCHEDULE_NOT_EXISTS, schedule.getId());
        }
    }

    private Schedule updateSchedule(Schedule schedule, WorkflowDefinition workflowDefinition,
                                    String scheduleExpression, WarningType warningType, int warningGroupId,
                                    FailureStrategy failureStrategy, Priority workflowInstancePriority,
                                    String workerGroup, String tenantCode, long environmentCode) {
        if (schedule.getReleaseState() == ReleaseState.ONLINE) {
            log.warn("Schedule can not be updated due to schedule is {}, scheduleId:{}.",
                    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.");

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Take the schedule offline first (PUT /schedule/{id}/offline or state API), then update it, then set it online again.
  2. Check schedule.getReleaseState() == OFFLINE before issuing an update in automation code.
  3. If the schedule is stuck ONLINE, verify the workflow's schedule state in the UI and offline it there.

Example fix

// before
schedulerService.updateSchedule(...); // fails: schedule ONLINE
// after
schedulerService.setScheduleState(loginUser, projectCode, scheduleId, ReleaseState.OFFLINE);
schedulerService.updateSchedule(...);
schedulerService.setScheduleState(loginUser, projectCode, scheduleId, ReleaseState.ONLINE);
Defensive patterns

Strategy: try-catch

Validate before calling

Schedule s = schedulerMapper.selectById(scheduleId);
if (s != null && s.getReleaseState() == ReleaseState.ONLINE) {
    throw new IllegalStateException("Offline schedule " + scheduleId + " before updating");
}

Try / catch

try {
    schedulerService.updateSchedule(...);
} catch (ServiceException e) {
    if (e.getCode() == Status.SCHEDULE_CRON_ONLINE_FORBID_UPDATE) {
        // offline the schedule, retry, then re-online
    } else { throw e; }
}

Prevention

When it happens

Trigger: PUT /schedule/{id} (updateSchedule) on a schedule whose Schedule.releaseState == ReleaseState.ONLINE.

Common situations: Operator edits a cron expression through the UI/API while the schedule is published; automation scripts that update schedules without checking release state.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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