{"record":{"id":"4521416db293bbea","repo":"apache/dolphinscheduler","slug":"schedule-cron-online-forbid-update","errorCode":"SCHEDULE_CRON_ONLINE_FORBID_UPDATE","errorMessage":"Schedule can not be updated due to schedule is {}, scheduleId:{}.","messagePattern":"Schedule can not be updated due to schedule is (.+?), scheduleId:(.+?)\\.","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java","lineNumber":537,"sourceCode":"    }\n\n    private void checkScheduleBelongsToProject(Schedule schedule, long projectCode) {\n        if (schedule == null) {\n            return;\n        }\n        WorkflowDefinition workflowDefinition =\n                workflowDefinitionDao.queryByCode(schedule.getWorkflowDefinitionCode()).orElse(null);\n        if (workflowDefinition == null || workflowDefinition.getProjectCode() != projectCode) {\n            throw new ServiceException(Status.SCHEDULE_NOT_EXISTS, schedule.getId());\n        }\n    }\n\n    private Schedule updateSchedule(Schedule schedule, WorkflowDefinition workflowDefinition,\n                                    String scheduleExpression, WarningType warningType, int warningGroupId,\n                                    FailureStrategy failureStrategy, Priority workflowInstancePriority,\n                                    String workerGroup, String tenantCode, long environmentCode) {\n        if (schedule.getReleaseState() == ReleaseState.ONLINE) {\n            log.warn(\"Schedule can not be updated due to schedule is {}, scheduleId:{}.\",\n                    ReleaseState.ONLINE.getDescp(), schedule.getId());\n            throw new ServiceException(Status.SCHEDULE_CRON_ONLINE_FORBID_UPDATE);\n        }\n\n        Date now = new Date();\n\n        tenantExistValidator.validate(tenantCode);\n        schedule.setTenantCode(tenantCode);\n\n        // updateWorkflowInstance param\n        if (!StringUtils.isEmpty(scheduleExpression)) {\n            ScheduleParam scheduleParam = JSONUtils.parseObject(scheduleExpression, ScheduleParam.class);\n            if (scheduleParam == null) {\n                log.warn(\"Parameter scheduleExpression is invalid, so parse cron error.\");\n                throw new ServiceException(Status.PARSE_TO_CRON_EXPRESSION_ERROR);\n            }\n            if (DateUtils.differSec(scheduleParam.getStartTime(), scheduleParam.getEndTime()) == 0) {\n                log.warn(\"The start time must not be the same as the end or time can not be null.\");","sourceCodeStart":519,"sourceCodeEnd":555,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java#L519-L555","documentation":"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.","triggerScenarios":"PUT /schedule/{id} (updateSchedule) on a schedule whose Schedule.releaseState == ReleaseState.ONLINE.","commonSituations":"Operator edits a cron expression through the UI/API while the schedule is published; automation scripts that update schedules without checking release state.","solutions":["Take the schedule offline first (PUT /schedule/{id}/offline or state API), then update it, then set it online again.","Check schedule.getReleaseState() == OFFLINE before issuing an update in automation code.","If the schedule is stuck ONLINE, verify the workflow's schedule state in the UI and offline it there."],"exampleFix":"// before\nschedulerService.updateSchedule(...); // fails: schedule ONLINE\n// after\nschedulerService.setScheduleState(loginUser, projectCode, scheduleId, ReleaseState.OFFLINE);\nschedulerService.updateSchedule(...);\nschedulerService.setScheduleState(loginUser, projectCode, scheduleId, ReleaseState.ONLINE);","handlingStrategy":"try-catch","validationCode":"Schedule s = schedulerMapper.selectById(scheduleId);\nif (s != null && s.getReleaseState() == ReleaseState.ONLINE) {\n    throw new IllegalStateException(\"Offline schedule \" + scheduleId + \" before updating\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    schedulerService.updateSchedule(...);\n} catch (ServiceException e) {\n    if (e.getCode() == Status.SCHEDULE_CRON_ONLINE_FORBID_UPDATE) {\n        // offline the schedule, retry, then re-online\n    } else { throw e; }\n}","preventionTips":["Always offline a schedule before editing its cron/params.","In automation, query release state before issuing updates.","Wrap offline -> update -> online in one runbook/script to leave state consistent."],"tags":["scheduler","release-state","concurrent-edit"],"backgroundTag":"invalid-state-transition","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}