{"record":{"id":"f84f7cf77f0a721e","repo":"apache/dolphinscheduler","slug":"20016-f84f7c","errorCode":"20016","errorMessage":"resource not exist or no permission,please view the task node and remove error resource","messagePattern":"resource not exist or no permission,please view the task node and remove error resource","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskSubWorkflowPermissionChecker.java","lineNumber":79,"sourceCode":"            if (!TaskTypeUtils.isSubWorkflowTask(taskDefinition.getTaskType())) {\n                continue;\n            }\n            SubWorkflowParameters subWorkflowParameters =\n                    JSONUtils.parseObject(taskDefinition.getTaskParams(), SubWorkflowParameters.class);\n            if (subWorkflowParameters.getWorkflowDefinitionCode() > 0) {\n                subWorkflowDefinitionCodes.add(subWorkflowParameters.getWorkflowDefinitionCode());\n            }\n        }\n\n        if (subWorkflowDefinitionCodes.isEmpty()) {\n            return;\n        }\n\n        List<WorkflowDefinition> subWorkflowDefinitions =\n                workflowDefinitionDao.queryByCodes(subWorkflowDefinitionCodes);\n        if (subWorkflowDefinitions == null) {\n            log.warn(\"Referenced sub workflow is unavailable, userId:{}.\", loginUser.getId());\n            throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);\n        }\n        Set<Long> existingSubWorkflowDefinitionCodes =\n                subWorkflowDefinitions.stream().map(WorkflowDefinition::getCode).collect(Collectors.toSet());\n        if (!existingSubWorkflowDefinitionCodes.containsAll(subWorkflowDefinitionCodes)) {\n            log.warn(\"Referenced sub workflow is unavailable, userId:{}.\", loginUser.getId());\n            throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);\n        }\n\n        Set<Long> subWorkflowProjectCodes = subWorkflowDefinitions.stream()\n                .map(WorkflowDefinition::getProjectCode)\n                .collect(Collectors.toSet());\n        try {\n            for (Long projectCode : subWorkflowProjectCodes) {\n                projectService.checkHasProjectWritePermissionThrowException(loginUser, projectCode);\n            }\n        } catch (ServiceException ex) {\n            log.warn(\"Referenced sub workflow is unavailable, userId:{}.\", loginUser.getId());\n            throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskSubWorkflowPermissionChecker.java#L61-L97","documentation":"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.","triggerScenarios":"A SUB_PROCESS/dependent task references sub-workflow codes that were deleted or never existed, so queryByCodes yields no rows (null).","commonSituations":"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.","solutions":["Open the task node and update/clear the sub-workflow reference to an existing workflow","Recreate the deleted sub-workflow (or re-import it from the source environment)","Check the referenced workflow codes against t_ds_workflow_definition","Redeploy the parent workflow with valid resource references"],"exampleFix":"// before\nList<WorkflowDefinition> defs = workflowDefinitionDao.queryByCodes(codes);\nif (defs == null) throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);\n// after: validate references up front\nlong existing = codes.stream().filter(c -> workflowDefinitionDao.findDefinitionByCode(c) != null).count();\nif (existing != codes.size()) {\n    throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);\n}","handlingStrategy":"validation","validationCode":"// before saving a task referencing sub-workflows\nfor (Long code : subWorkflowDefinitionCodes) {\n    if (workflowDefinitionDao.findDefinitionByCode(code) == null) {\n        throw new ServiceException(\"sub workflow \" + code + \" does not exist\");\n    }\n}","typeGuard":"boolean allSubWorkflowsExist(Set<Long> codes) {\n    List<WorkflowDefinition> defs = workflowDefinitionDao.queryByCodes(new ArrayList<>(codes));\n    return defs != null && defs.stream().map(WorkflowDefinition::getCode)\n        .collect(Collectors.toSet()).containsAll(codes);\n}","tryCatchPattern":"try {\n    taskDefinitionService.updateTaskDefinition(...);\n} catch (ServiceException e) {\n    if (e.getCode() == 20016) {\n        log.warn(\"referenced sub workflow missing - repair task node\");\n    }\n    throw e;\n}","preventionTips":["Check referenced workflows exist before cross-environment deployment","Block deletion of workflows used as SUB_PROCESS targets","Validate task JSON after imports/migrations","Use UI pickers rather than manually typing workflow codes"],"tags":["sub-workflow","reference-integrity","task-definition"],"backgroundTag":"resource-not-found","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}