{"record":{"id":"c2f663c2c18f3a0f","repo":"apache/dolphinscheduler","slug":"schedule-already-exists","errorCode":"SCHEDULE_ALREADY_EXISTS","errorMessage":"SCHEDULE_ALREADY_EXISTS: schedule already exists for workflow definition {workflowDefinitionCode}, scheduleId {scheduleId}","messagePattern":"SCHEDULE_ALREADY_EXISTS: schedule already exists for workflow definition (.+?), 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":142,"sourceCode":"                                   String workerGroup,\n                                   String tenantCode,\n                                   Long environmentCode) {\n\n        Project project = projectDao.queryByCode(projectCode);\n\n        projectService.checkHasProjectWritePermissionThrowException(loginUser, project);\n\n        // check workflow define release state\n        WorkflowDefinition workflowDefinition = workflowDefinitionDao.queryByCode(workflowDefinitionCode).orElse(null);\n        executorService.checkWorkflowDefinitionValid(projectCode, workflowDefinition, workflowDefinitionCode,\n                workflowDefinition.getVersion());\n\n        Schedule scheduleExists =\n                scheduleDao.queryByWorkflowDefinitionCode(workflowDefinitionCode);\n        if (scheduleExists != null) {\n            log.error(\"Schedule already exist, scheduleId:{}, workflowDefinitionCode:{}\", scheduleExists.getId(),\n                    workflowDefinitionCode);\n            throw new ServiceException(Status.SCHEDULE_ALREADY_EXISTS, workflowDefinitionCode,\n                    scheduleExists.getId());\n        }\n\n        Schedule scheduleObj = new Schedule();\n        Date now = new Date();\n\n        tenantExistValidator.validate(tenantCode);\n\n        scheduleObj.setTenantCode(tenantCode);\n        scheduleObj.setProjectName(project.getName());\n        scheduleObj.setWorkflowDefinitionCode(workflowDefinitionCode);\n        scheduleObj.setWorkflowDefinitionName(workflowDefinition.getName());\n\n        ScheduleParam scheduleParam = JSONUtils.parseObject(schedule, ScheduleParam.class);\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.\");\n            throw new ServiceException(Status.SCHEDULE_START_TIME_END_TIME_SAME);\n        }","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SchedulerServiceImpl.java#L124-L160","documentation":"SchedulerServiceImpl.insertSchedule throws ServiceException(Status.SCHEDULE_ALREADY_EXISTS, workflowDefinitionCode, scheduleId) when a schedule already exists for the given workflow definition code: scheduleDao.queryByWorkflowDefinitionCode returns non-null. DolphinScheduler enforces at most one schedule (timed workflow trigger) per workflow definition, so creating a second is rejected. The message includes the existing schedule's id.","triggerScenarios":"POST /schedules for a workflow definition that already has a timed schedule; double-submitting the create-schedule form; retrying a create call after a timeout when the first request actually succeeded.","commonSituations":"UI double-click on 'Create Schedule'; automation that creates schedules without checking existing ones; retry logic re-running a request that partially succeeded.","solutions":["Query existing schedules for the workflow definition first (queryScheduleList) and reuse or update the existing schedule instead of inserting.","If you need different timing, update the existing schedule (updateSchedule) rather than creating a new one.","Deduplicate automation/retry logic: make the create idempotent by catching SCHEDULE_ALREADY_EXISTS and treating it as success."],"exampleFix":"// before: unconditional insert\nschedulerService.insertSchedule(loginUser, projectCode, workflowDefinitionCode, schedule);\n\n// after: idempotent guard\nif (scheduleDao.queryByWorkflowDefinitionCode(workflowDefinitionCode) == null) {\n    schedulerService.insertSchedule(loginUser, projectCode, workflowDefinitionCode, schedule);\n} else {\n    schedulerService.updateSchedule(loginUser, projectCode, existingId, schedule);\n}","handlingStrategy":"validation","validationCode":"// check for an existing schedule before inserting\nSchedule existing = scheduleDao.queryByWorkflowDefinitionCode(workflowDefinitionCode);\nif (existing != null) {\n    throw new IllegalStateException(\"Schedule \" + existing.getId() + \" already exists for workflow \" + workflowDefinitionCode);\n}","typeGuard":null,"tryCatchPattern":"try {\n    schedulerService.insertSchedule(loginUser, projectCode, workflowDefinitionCode, schedule);\n} catch (ServiceException e) {\n    if (Status.SCHEDULE_ALREADY_EXISTS.getCode() == e.getCode()) {\n        // update existing schedule instead\n    } else { throw e; }\n}","preventionTips":["Always query existing schedules before creating","Debounce create-schedule form submissions","Make automation idempotent by updating instead of inserting"],"tags":["scheduler","duplicate","workflow"],"backgroundTag":"duplicate-entity","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}