apache/dolphinscheduler · error · ServiceException

SCHEDULE_STATE_ONLINE

SCHEDULE_STATE_ONLINE

Error message

SCHEDULE_STATE_ONLINE: schedule {scheduleId} is already online

What it means

SCHEDULE_STATE_ONLINE is thrown by deleteSchedulesById when the schedule's ReleaseState is ONLINE. A schedule attached to a running quartz trigger cannot be deleted; it must first be taken offline (set to OFFLINE) via the schedule online/offline endpoint. The message interpolates the scheduleId.

Source

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

        }
        return scheduleList;
    }

    /**
     * delete schedule by id
     *
     * @param loginUser   login user
     * @param scheduleId  schedule id
     */
    @Override
    public void deleteSchedulesById(User loginUser, Integer scheduleId) {
        Schedule schedule = scheduleDao.queryById(scheduleId);
        if (schedule == null) {
            throw new ServiceException(Status.SCHEDULE_NOT_EXISTS, scheduleId);
        }
        // check schedule is already online
        if (schedule.getReleaseState() == ReleaseState.ONLINE) {
            throw new ServiceException(Status.SCHEDULE_STATE_ONLINE, scheduleId);
        }
        // Determine if the login user is the owner of the schedule
        if (loginUser.getId() != schedule.getUserId() && loginUser.getUserType() != UserType.ADMIN_USER) {
            throw new ServiceException(Status.USER_NO_OPERATION_PERM);
        }

        this.projectPermCheckByWorkflowCode(loginUser, schedule.getWorkflowDefinitionCode());
        boolean delete = scheduleDao.deleteById(scheduleId);
        if (!delete) {
            throw new ServiceException(Status.DELETE_SCHEDULE_BY_ID_ERROR);
        }
    }

    /**
     * preview schedule
     *
     * @param loginUser login user
     * @param schedule  schedule expression

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Take the schedule offline first: POST /projects/{projectCode}/schedule/{id}/offline, then retry the delete.
  2. Alternatively pause or unpublish the workflow's timing in the UI before deleting.
  3. In bulk scripts, iterate: for each schedule check releaseState == OFFLINE before calling delete.

Example fix

// before
curl -X DELETE '/projects/1/schedules/42'        // schedule is ONLINE -> rejected
// after
curl -X POST '/projects/1/schedule/42/offline'
curl -X DELETE '/projects/1/schedules/42'
Defensive patterns

Strategy: validation

Validate before calling

Schedule s = scheduleDao.queryById(scheduleId);
if (s != null && s.getReleaseState() == ReleaseState.ONLINE) {
    schedulerService.setScheduleState(loginUser, projectCode, scheduleId, ReleaseState.OFFLINE); // offline first
}

Try / catch

try { schedulerService.deleteSchedulesById(user, scheduleId); } catch (ServiceException e) { if (e.getCode() == Status.SCHEDULE_STATE_ONLINE) { /* call offline endpoint, then retry delete */ } }

Prevention

When it happens

Trigger: DELETE /projects/{projectCode}/schedules/{id} where the schedule was published (POST .../schedule/{id}/online was called or the UI published it) and has not been switched offline.

Common situations: Deleting timing configurations during a cleanup while the workflows are still scheduled and running; bulk delete scripts that skip the offline step; environments where schedules are online by default after deployment.

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/193c8569051d99bd. Report an issue: GitHub.