apache/dolphinscheduler · error · ServiceException
DELETE_QUEUE_BY_ID_ERROR
DELETE_QUEUE_BY_ID_ERROR
Error message
DELETE_QUEUE_BY_ID_ERROR: delete queue by id error
What it means
QueueServiceImpl.deleteQueueById throws ServiceException(Status.DELETE_QUEUE_BY_ID_ERROR) when queueDao.deleteById(id) returns false — the database delete affected no rows. All permission, existence, and reference checks passed, but the actual delete failed. This usually indicates a race (queue deleted concurrently between the existence check and the delete) or a persistence-layer problem.
Source
Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/QueueServiceImpl.java:242
if (Objects.isNull(queue)) {
log.error("Queue does not exist");
throw new ServiceException(Status.QUEUE_NOT_EXIST);
}
List<Tenant> tenantList = tenantDao.queryTenantListByQueueId(queue.getId());
if (CollectionUtils.isNotEmpty(tenantList)) {
log.warn("Delete queue failed, because there are {} tenants using it.", tenantList.size());
throw new ServiceException(Status.DELETE_TENANT_BY_ID_FAIL_TENANTS, tenantList.size());
}
List<User> userList = userDao.queryUserListByQueue(queue.getQueueName());
if (CollectionUtils.isNotEmpty(userList)) {
log.warn("Delete queue failed, because there are {} users using it.", userList.size());
throw new ServiceException(Status.DELETE_QUEUE_BY_ID_FAIL_USERS, userList.size());
}
if (!queueDao.deleteById(id)) {
throw new ServiceException(Status.DELETE_QUEUE_BY_ID_ERROR);
}
}
/**
* verify queue and queueName
*
* @param queue queue
* @param queueName queue name
* @return true if the queue name not exists, otherwise return false
*/
@Override
public void verifyQueue(String queue, String queueName) {
Queue queueValidator = new Queue(queueName, queue);
validQueue(queueValidator);
}
/**View on GitHub (pinned to 02eac45a1b)
Solutions
- Re-check whether the queue now exists — if it was deleted by a concurrent request, treat the operation as complete.
- Retry the delete once after confirming the id exists; transient races resolve on the second attempt.
- Check server logs and database health (locks, replication lag, mapper SQL) if the queue still exists after the failure.
Example fix
// before: no concurrency handling
queueService.deleteQueueById(loginUser, id);
// after: tolerate benign race
try {
queueService.deleteQueueById(loginUser, id);
} catch (ServiceException e) {
if (queueDao.queryById(id) == null) {
log.info("Queue {} already deleted concurrently", id);
} else {
throw e;
}
} Defensive patterns
Strategy: retry
Validate before calling
// verify the queue still exists before/after retry
if (queueDao.queryById(id) == null) { return; /* already gone */ } Try / catch
try {
queueService.deleteQueueById(loginUser, id);
} catch (ServiceException e) {
if (Status.DELETE_QUEUE_BY_ID_ERROR.getCode() == e.getCode() && queueDao.queryById(id) == null) {
// benign race: queue already deleted concurrently
} else { throw e; }
} Prevention
- Serialize delete operations through a single admin flow
- Retry once after re-checking existence
- Disable duplicate-click submission in UI tooling
When it happens
Trigger: Concurrent deletion: another request removed the queue between queryById and deleteById; transaction rollback or MyBatis mapper returning 0 affected rows due to a DB constraint/trigger or connection issue.
Common situations: Double-clicked delete buttons issuing two near-simultaneous deletes; automated retries racing each other; database replication/lock issues causing the delete statement to affect nothing.
Related errors
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/47f81bfd55165790.
Report an issue: GitHub.