apache/dolphinscheduler · error · ServiceException

20016

20016

Error message

resource not exist or no permission,please view the task node and remove error resource

What it means

TaskSubWorkflowPermissionChecker.checkPermission resolves the sub-workflow definition codes referenced by a task. If workflowDefinitionDao.queryByCodes returns null it throws ServiceException with Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION (20016). This is the 'no sub workflows found at all' branch.

Source

Thrown at dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskSubWorkflowPermissionChecker.java:79

            if (!TaskTypeUtils.isSubWorkflowTask(taskDefinition.getTaskType())) {
                continue;
            }
            SubWorkflowParameters subWorkflowParameters =
                    JSONUtils.parseObject(taskDefinition.getTaskParams(), SubWorkflowParameters.class);
            if (subWorkflowParameters.getWorkflowDefinitionCode() > 0) {
                subWorkflowDefinitionCodes.add(subWorkflowParameters.getWorkflowDefinitionCode());
            }
        }

        if (subWorkflowDefinitionCodes.isEmpty()) {
            return;
        }

        List<WorkflowDefinition> subWorkflowDefinitions =
                workflowDefinitionDao.queryByCodes(subWorkflowDefinitionCodes);
        if (subWorkflowDefinitions == null) {
            log.warn("Referenced sub workflow is unavailable, userId:{}.", loginUser.getId());
            throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
        }
        Set<Long> existingSubWorkflowDefinitionCodes =
                subWorkflowDefinitions.stream().map(WorkflowDefinition::getCode).collect(Collectors.toSet());
        if (!existingSubWorkflowDefinitionCodes.containsAll(subWorkflowDefinitionCodes)) {
            log.warn("Referenced sub workflow is unavailable, userId:{}.", loginUser.getId());
            throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
        }

        Set<Long> subWorkflowProjectCodes = subWorkflowDefinitions.stream()
                .map(WorkflowDefinition::getProjectCode)
                .collect(Collectors.toSet());
        try {
            for (Long projectCode : subWorkflowProjectCodes) {
                projectService.checkHasProjectWritePermissionThrowException(loginUser, projectCode);
            }
        } catch (ServiceException ex) {
            log.warn("Referenced sub workflow is unavailable, userId:{}.", loginUser.getId());
            throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Open the task node and update/clear the sub-workflow reference to an existing workflow
  2. Recreate the deleted sub-workflow (or re-import it from the source environment)
  3. Check the referenced workflow codes against t_ds_workflow_definition
  4. Redeploy the parent workflow with valid resource references

Example fix

// before
List<WorkflowDefinition> defs = workflowDefinitionDao.queryByCodes(codes);
if (defs == null) throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
// after: validate references up front
long existing = codes.stream().filter(c -> workflowDefinitionDao.findDefinitionByCode(c) != null).count();
if (existing != codes.size()) {
    throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);
}
Defensive patterns

Strategy: validation

Validate before calling

// before saving a task referencing sub-workflows
for (Long code : subWorkflowDefinitionCodes) {
    if (workflowDefinitionDao.findDefinitionByCode(code) == null) {
        throw new ServiceException("sub workflow " + code + " does not exist");
    }
}

Type guard

boolean allSubWorkflowsExist(Set<Long> codes) {
    List<WorkflowDefinition> defs = workflowDefinitionDao.queryByCodes(new ArrayList<>(codes));
    return defs != null && defs.stream().map(WorkflowDefinition::getCode)
        .collect(Collectors.toSet()).containsAll(codes);
}

Try / catch

try {
    taskDefinitionService.updateTaskDefinition(...);
} catch (ServiceException e) {
    if (e.getCode() == 20016) {
        log.warn("referenced sub workflow missing - repair task node");
    }
    throw e;
}

Prevention

When it happens

Trigger: A SUB_PROCESS/dependent task references sub-workflow codes that were deleted or never existed, so queryByCodes yields no rows (null).

Common situations: Sub-workflow deleted after the parent task was created; workflow imported/copied across environments where target workflows don't exist; code values corrupted by manual JSON editing.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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