{"record":{"id":"b9ef1eb10c4590c6","repo":"apache/dolphinscheduler","slug":"delete-schedule-by-id-error","errorCode":"DELETE_SCHEDULE_BY_ID_ERROR","errorMessage":"DELETE_SCHEDULE_BY_ID_ERROR: delete schedule by id error","messagePattern":"DELETE_SCHEDULE_BY_ID_ERROR: delete schedule by id error","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"warning","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java","lineNumber":366,"sourceCode":"    @Override\n    public void deleteSchedulesById(User loginUser, Integer scheduleId) {\n        Schedule schedule = scheduleDao.queryById(scheduleId);\n        if (schedule == null) {\n            throw new ServiceException(Status.SCHEDULE_NOT_EXISTS, scheduleId);\n        }\n        // check schedule is already online\n        if (schedule.getReleaseState() == ReleaseState.ONLINE) {\n            throw new ServiceException(Status.SCHEDULE_STATE_ONLINE, scheduleId);\n        }\n        // Determine if the login user is the owner of the schedule\n        if (loginUser.getId() != schedule.getUserId() && loginUser.getUserType() != UserType.ADMIN_USER) {\n            throw new ServiceException(Status.USER_NO_OPERATION_PERM);\n        }\n\n        this.projectPermCheckByWorkflowCode(loginUser, schedule.getWorkflowDefinitionCode());\n        boolean delete = scheduleDao.deleteById(scheduleId);\n        if (!delete) {\n            throw new ServiceException(Status.DELETE_SCHEDULE_BY_ID_ERROR);\n        }\n    }\n\n    /**\n     * preview schedule\n     *\n     * @param loginUser login user\n     * @param schedule  schedule expression\n     * @return the next five fire time\n     */\n    @Override\n    public List<String> previewSchedule(User loginUser, String schedule) {\n        Cron cron;\n        ScheduleParam scheduleParam = JSONUtils.parseObject(schedule, ScheduleParam.class);\n\n        assert scheduleParam != null;\n        ZoneId zoneId = TimeZone.getTimeZone(scheduleParam.getTimezoneId()).toZoneId();\n        ZonedDateTime now = ZonedDateTime.now(zoneId);","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java#L348-L384","documentation":"DELETE_SCHEDULE_BY_ID_ERROR is thrown by deleteSchedulesById when scheduleDao.deleteById(scheduleId) returns false — all prior checks (existence, offline state, ownership, project permission) passed, but the database delete affected no rows. This usually indicates a concurrent delete or a persistence-layer failure.","triggerScenarios":"DELETE /projects/{projectCode}/schedules/{id} racing with another user/script deleting the same schedule between queryById and deleteById; DB transaction rollback, lock timeout, or constraint failure inside scheduleDao.deleteById.","commonSituations":"Two operators deleting the same timing in the UI at once; duplicate cleanup cron jobs hitting the API concurrently; database connectivity/lock issues under load; replication lag in read/write split setups where the read saw the row but the write replica had already removed it.","solutions":["Re-fetch the schedule; if it no longer exists, treat the delete as already completed and continue.","Retry the delete once after a short delay to absorb transient DB/lock failures.","Serialize cleanup jobs (single worker or distributed lock) so two processes cannot delete the same schedule concurrently.","Check database logs for lock timeouts or rollback causes if the error persists."],"exampleFix":"// before\nfor id in ids: deleteSchedule(id)          // two workers race -> one fails here\n// after\nwith distributed_lock(\"schedule-cleanup\"):\n    for id in ids: deleteSchedule(id)      # skip if GET shows schedule gone","handlingStrategy":"retry","validationCode":"Schedule s = scheduleDao.queryById(scheduleId);\nif (s == null) return; // nothing to delete\nboolean deleted = scheduleDao.deleteById(scheduleId);\nif (!deleted) { /* retry once, then re-check existence */ }","typeGuard":null,"tryCatchPattern":"try { schedulerService.deleteSchedulesById(user, scheduleId); } catch (ServiceException e) { if (e.getCode() == Status.DELETE_SCHEDULE_BY_ID_ERROR) { /* re-check existence; if absent, treat as success, else retry with backoff */ } }","preventionTips":["Serialize schedule deletions with a lock to avoid concurrent deletes","Add one retry with backoff around schedule deletes","Monitor DB for lock timeouts; check dao delete affected-row semantics"],"tags":["scheduler","concurrency","database"],"backgroundTag":"database-write-failed","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"}