{"record":{"id":"7551c58949ed97bf","repo":"apache/dolphinscheduler","slug":"20016","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/TaskDatasourcePermissionChecker.java","lineNumber":84,"sourceCode":"            if (datasourceResources == null) {\n                continue;\n            }\n            datasourceResources.keySet().stream()\n                    .filter(datasourceId -> datasourceId != null && datasourceId > 0)\n                    .forEach(datasourceIds::add);\n        }\n\n        if (datasourceIds.isEmpty()) {\n            return;\n        }\n\n        int userId = loginUser.getUserType() == UserType.ADMIN_USER ? 0 : loginUser.getId();\n        Integer[] datasourceIdArray = datasourceIds.toArray(new Integer[0]);\n        if (!resourcePermissionCheckService.resourcePermissionCheck(\n                AuthorizationType.DATASOURCE, datasourceIdArray, userId, log)) {\n            log.warn(\"User does not have permission to use datasource referenced by task, userId:{}.\",\n                    loginUser.getId());\n            throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);\n        }\n    }\n}\n","sourceCodeStart":66,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/permission/TaskDatasourcePermissionChecker.java#L66-L88","documentation":"TaskDatasourcePermissionChecker.checkPermission validates that the task's referenced datasource ids are usable by the caller. It delegates to resourcePermissionCheckService.resourcePermissionCheck for AuthorizationType.DATASOURCE (admins pass userId=0 which checks existence only). On failure it throws ServiceException with Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION (code 20016).","triggerScenarios":"Saving/updating a task definition whose datasourceIds reference a datasource that either no longer exists or is owned by another user (non-admin).","commonSituations":"A datasource was deleted while tasks still reference it; a colleague's task copied into your workflow without being granted the datasource; switching from admin to normal user changes the check from existence-only to ownership.","solutions":["Open the task node and remove or replace the invalid/unauthorized datasource reference","Grant the user permission to the datasource (UI: Security -> Datasource -> grant)","Verify the datasource id still exists in t_ds_datasource","If you are the admin checking existence, confirm the datasource wasn't deleted"],"exampleFix":"// before: datasourceIds kept from copied task\ntaskDefinitionService.updateTask(...);\n// after: pre-check in caller\nInteger[] ids = params.getDatasourceIds();\nif (!resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.DATASOURCE, ids, loginUser.getId(), log)) {\n    throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);\n}","handlingStrategy":"validation","validationCode":"// before saving a task definition\nfor (Integer dsId : taskParams.getDatasourceIds()) {\n    DataSource ds = dataSourceService.getDataSource(dsId);\n    if (ds == null) throw new ServiceException(\"datasource \" + dsId + \" not exist\");\n    if (loginUser.getUserType() != UserType.ADMIN_USER && ds.getUserId() != loginUser.getId()) {\n        throw new ServiceException(\"no permission on datasource \" + dsId);\n    }\n}","typeGuard":"boolean canUseDatasources(User loginUser, List<Integer> ids) {\n    int userId = loginUser.getUserType() == UserType.ADMIN_USER ? 0 : loginUser.getId();\n    return resourcePermissionCheckService.resourcePermissionCheck(\n        AuthorizationType.DATASOURCE, ids.toArray(new Integer[0]), userId, log);\n}","tryCatchPattern":"try {\n    taskDefinitionService.updateTaskDefinition(...);\n} catch (ServiceException e) {\n    if (e.getCode() == Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION.getCode()) {\n        log.warn(\"fix datasource references in task node before saving\");\n    }\n    throw e;\n}","preventionTips":["Re-validate datasource references after copying tasks between users/projects","Warn before deleting a datasource still referenced by tasks","Re-check permissions when switching accounts from admin to normal user","Keep datasource ids out of hand-edited JSON"],"tags":["authorization","datasource","task-definition"],"backgroundTag":"insufficient-permissions","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"}