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

  1. Re-check whether the queue now exists — if it was deleted by a concurrent request, treat the operation as complete.
  2. Retry the delete once after confirming the id exists; transient races resolve on the second attempt.
  3. 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

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.