apache/dolphinscheduler · error · ServiceException
50041
50041
Error message
delete task definition version error
What it means
Thrown when the delete of a task definition version from t_ds_task_definition_log affects zero rows (taskDefinitionLogMapper.deleteByCodeAndVersion returned <= 0). It means the requested (code, version) pair does not exist in the version-history table, so nothing was deleted.
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TaskDefinitionServiceImpl.java:286
// check if user have write perm for project
projectService.checkHasProjectWritePermissionThrowException(loginUser, project);
TaskDefinition taskDefinition = taskDefinitionDao.queryByCode(taskCode);
if (taskDefinition == null || projectCode != taskDefinition.getProjectCode()) {
log.error("Task definition does not exist, taskDefinitionCode:{}.", taskCode);
throw new ServiceException(Status.TASK_DEFINE_NOT_EXIST, String.valueOf(taskCode));
}
if (taskDefinition.getVersion() == version) {
log.warn(
"Task definition can not be deleted due to version is being used, projectCode:{}, taskDefinitionCode:{}, version:{}.",
projectCode, taskCode, version);
throw new ServiceException(Status.MAIN_TABLE_USING_VERSION);
}
int delete = taskDefinitionLogMapper.deleteByCodeAndVersion(taskCode, version);
if (delete <= 0) {
log.error("Task definition version delete error, projectCode:{}, taskDefinitionCode:{}, version:{}.",
projectCode, taskCode, version);
throw new ServiceException(Status.DELETE_TASK_DEFINITION_VERSION_ERROR);
}
log.info(
"Task definition version delete complete, projectCode:{}, taskDefinitionCode:{}, version:{}.",
projectCode, taskCode, version);
}
@Override
public TaskDefinitionVO queryTaskDefinitionDetail(User loginUser, long projectCode, long taskCode) {
Project project = projectDao.queryByCode(projectCode);
// check user access for project
projectService.checkProjectAndAuthThrowException(loginUser, project, TASK_DEFINITION);
TaskDefinition taskDefinition = taskDefinitionDao.queryByCode(taskCode);
if (taskDefinition == null || projectCode != taskDefinition.getProjectCode()) {
log.error("Task definition does not exist, taskDefinitionCode:{}.", taskCode);
throw new ServiceException(Status.TASK_DEFINE_NOT_EXIST, String.valueOf(taskCode));
}
List<WorkflowTaskRelation> taskRelationList = workflowTaskRelationDaoView on GitHub (pinned to 02eac45a1b)
Solutions
- Verify the version exists before deleting: taskDefinitionLogMapper.queryByDefinitionCodeAndVersion(code, version) != null.
- Make cleanup scripts idempotent: treat zero-row deletes as success rather than retrying.
- Catch ServiceException code 50041 and log the (code, version) pair for diagnosis instead of failing the whole batch.
Example fix
// before
taskDefinitionService.deleteByCodeAndVersion(loginUser, projectCode, code, version); // throws if rows==0
// after
if (taskDefinitionLogMapper.queryByDefinitionCodeAndVersion(code, version) != null) {
taskDefinitionService.deleteByCodeAndVersion(loginUser, projectCode, code, version);
} Defensive patterns
Strategy: validation
Validate before calling
TaskDefinitionLog log = taskDefinitionLogMapper.queryByDefinitionCodeAndVersion(code, version);
if (log == null) { throw new IllegalStateException("version " + version + " not in history"); } Type guard
boolean versionExists(TaskDefinitionLog l) {
return l != null && l.getVersion() > 0;
} Try / catch
try {
taskDefinitionService.deleteByCodeAndVersion(loginUser, projectCode, code, version);
} catch (ServiceException e) {
if (e.getCode() == 50041) { /* already deleted: treat as success in idempotent scripts */ }
else { throw e; }
} Prevention
- Query version history before deleting to confirm the exact version number.
- Avoid retry loops around delete operations; make them idempotent.
- Guard against double-execution in cleanup jobs using a processed-versions set.
When it happens
Trigger: Calling deleteByCodeAndVersion with a version number that was never persisted to the log table (typo, already deleted, version beyond history), while the version check against the master table passed.
Common situations: Double-deleting the same version from concurrent scripts or retries; off-by-one when enumerating versions; environments where history was purged externally.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/ea14c75f4934495d.
Report an issue: GitHub.