apache/dolphinscheduler · error · ServiceException

USER_NO_OPERATION_PERM

USER_NO_OPERATION_PERM

Error message

USER_NO_OPERATION_PERM: user has no operation privilege

What it means

Thrown in deleteWorkflowDefinitionByCode when the login user is neither the owner (userId mismatch) nor an ADMIN_USER. Only the workflow's creator or an admin may delete it; project write permission alone (checked just before) is not sufficient.

Source

Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java:880

                workflowDefinition.getProjectCode(), workflowDefinition.getCode(), 0);

        if (taskDepMsg.isPresent()) {
            String errorMeg = "workflow definition cannot be deleted because it has dependent, " + taskDepMsg.get();
            log.error(errorMeg);
            throw new ServiceException(errorMeg);
        }
    }

    public void deleteWorkflowDefinitionByCode(User loginUser, long code) {
        WorkflowDefinition workflowDefinition = workflowDefinitionDao.queryByCode(code)
                .orElseThrow(() -> new ServiceException(WORKFLOW_DEFINITION_NOT_EXIST, String.valueOf(code)));

        Project project = projectDao.queryByCode(workflowDefinition.getProjectCode());
        projectService.checkHasProjectWritePermissionThrowException(loginUser, project);

        // Determine if the login user is the owner of the workflow definition
        if (loginUser.getId() != workflowDefinition.getUserId() && loginUser.getUserType() != UserType.ADMIN_USER) {
            throw new ServiceException(Status.USER_NO_OPERATION_PERM);
        }

        workflowDefinitionUsedInOtherTaskValid(loginUser, workflowDefinition);

        // get the timing according to the workflow definition
        Schedule scheduleObj = scheduleDao.queryByWorkflowDefinitionCode(code);
        if (scheduleObj != null) {
            if (scheduleObj.getReleaseState() == ReleaseState.OFFLINE) {
                boolean delete = scheduleDao.deleteById(scheduleObj.getId());
                if (!delete) {
                    throw new ServiceException(Status.DELETE_SCHEDULE_BY_ID_ERROR);
                }
            }
            if (scheduleObj.getReleaseState() == ReleaseState.ONLINE) {
                throw new ServiceException(Status.SCHEDULE_STATE_ONLINE, scheduleObj.getId());
            }
        }

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Log in as (or run the call as) the workflow owner or an ADMIN_USER.
  2. Have an admin delete the workflow on the user's behalf.
  3. Reassign the workflow's user_id to the intended operator in the DB if ownership needs transfer.

Example fix

// before
User operator = userService.getUserByName("analyst"); // not owner
service.deleteWorkflowDefinitionByCode(operator, code);
// after
User admin = userService.getUserByName("admin");
service.deleteWorkflowDefinitionByCode(admin, code);
Defensive patterns

Strategy: validation

Validate before calling

WorkflowDefinition wf = workflowDefinitionDao.queryByCode(code).orElseThrow(NoSuchElementException::new);
boolean allowed = loginUser.getId() == wf.getUserId() || loginUser.getUserType() == UserType.ADMIN_USER;
if (!allowed) throw new SecurityException("only owner or admin can delete");

Type guard

boolean canDelete(User u, WorkflowDefinition wf) {
    return u.getId() == wf.getUserId() || u.getUserType() == UserType.ADMIN_USER;
}

Try / catch

try { service.deleteWorkflowDefinitionByCode(user, code); }
catch (ServiceException e) { if (e.getCode() == Status.USER_NO_OPERATION_PERM) { /* escalate to admin or reassign ownership */ } }

Prevention

When it happens

Trigger: A non-admin user calling deleteWorkflowDefinitionByCode for a workflow created by another user, even with project write permission granted.

Common situations: Team members sharing a project but each owning their own workflows; service accounts operating under a non-admin user; scripts running as a generic user instead of the owner.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/6ca9d0b9e06a9e82. Report an issue: GitHub.