{"record":{"id":"268f83d5fcde7d4f","repo":"apache/dolphinscheduler","slug":"30003","errorCode":"30003","errorMessage":"user [{userName}] does not have write permission for project [{projectCode}]","messagePattern":"user \\[(.+?)\\] does not have write permission for project \\[(.+?)\\]","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TaskGroupServiceImpl.java","lineNumber":298,"sourceCode":"        Project project = projectDao.queryByCode(projectCode);\n        if (project == null) {\n            log.warn(\"Project does not exist, projectCode:{}.\", projectCode);\n            throw new ServiceException(Status.PROJECT_NOT_FOUND, projectCode);\n        }\n        if (project.getUserId().equals(loginUser.getId())) {\n            return;\n        }\n        ProjectUser projectUser = projectUserDao.queryProjectRelation(project.getId(), loginUser.getId());\n        if (projectUser == null) {\n            log.warn(\"User {} does not have operation permission for project {}\", loginUser.getUserName(),\n                    project.getCode());\n            throw new ServiceException(Status.USER_NO_OPERATION_PROJECT_PERM, loginUser.getUserName(),\n                    project.getCode());\n        }\n        if (writePermission && projectUser.getPerm() != Constants.DEFAULT_ADMIN_PERMISSION) {\n            log.warn(\"User {} does not have write permission for project {}\", loginUser.getUserName(),\n                    project.getCode());\n            throw new ServiceException(Status.USER_NO_WRITE_PROJECT_PERM, loginUser.getUserName(),\n                    project.getCode());\n        }\n    }\n}\n","sourceCodeStart":280,"sourceCodeEnd":303,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TaskGroupServiceImpl.java#L280-L303","documentation":"Thrown by requireProjectPerm when writePermission is requested and the caller's project relation perm is not Constants.DEFAULT_ADMIN_PERMISSION (2, i.e. read-write). The user can see the project but holds read-only permission, so write operations on task groups are refused. Reported as Status.USER_NO_WRITE_PROJECT_PERM (code 30003) with userName and projectCode interpolated.","triggerScenarios":"createTaskGroup or updateTaskGroup called by a user whose projectUser.getPerm() is read-only (not 2); queryTaskGroupByProjectCode with writePermission=false never hits this; read-only grantees attempting to modify task group config.","commonSituations":"User granted 'view only' project permission trying to create task groups; permission downgraded to read-only by an admin while user's scripts still write; confusing read access with write access when designing roles.","solutions":["Ask an admin to upgrade the user's project permission to read-write (perm = 2 / DEFAULT_ADMIN_PERMISSION).","Have the project owner perform the write operation.","Check the perm column in t_ds_relation_project_user for this user/project pair.","Use read-only APIs (queryTaskGroupByProjectCode with writePermission=false) if only listing is needed."],"exampleFix":"// before\n// read-only user attempts create\ntaskGroupService.createTaskGroup(loginUser, name, desc, total, projectCode);\n// after\nProjectUser rel = projectUserDao.queryProjectRelation(project.getId(), loginUser.getId());\nboolean canWrite = loginUser.getUserType() == UserType.ADMIN_USER\n        || project.getUserId().equals(loginUser.getId())\n        || (rel != null && rel.getPerm() == Constants.DEFAULT_ADMIN_PERMISSION);\nif (!canWrite) {\n    throw new ServiceException(Status.USER_NO_WRITE_PROJECT_PERM,\n            loginUser.getUserName(), project.getCode());\n}","handlingStrategy":"validation","validationCode":"// Java: verify read-write permission before write operations\nProjectUser rel = projectUserDao.queryProjectRelation(project.getId(), loginUser.getId());\nboolean canWrite = loginUser.getUserType() == UserType.ADMIN_USER\n        || project.getUserId().equals(loginUser.getId())\n        || (rel != null && rel.getPerm() == Constants.DEFAULT_ADMIN_PERMISSION);\nif (!canWrite) throw new ServiceException(Status.USER_NO_WRITE_PROJECT_PERM,\n        loginUser.getUserName(), project.getCode());","typeGuard":"boolean hasProjectWriteAccess(User loginUser, Project project) {\n    ProjectUser rel = projectUserDao.queryProjectRelation(project.getId(), loginUser.getId());\n    return loginUser.getUserType() == UserType.ADMIN_USER\n            || project.getUserId().equals(loginUser.getId())\n            || (rel != null && rel.getPerm() == Constants.DEFAULT_ADMIN_PERMISSION);\n}","tryCatchPattern":"try {\n    taskGroupService.createTaskGroup(loginUser, name, desc, total, projectCode);\n} catch (ServiceException e) {\n    if (e.getCode() == 30003) {\n        // ask an admin to upgrade the grant to read-write (perm = 2)\n    }\n    throw e;\n}","preventionTips":["Grant read-write (perm 2), not read-only, to users who must create or edit task groups.","Use read-only APIs for listing when write access is absent.","Re-verify perm values after permission downgrades.","Distinguish read vs write grants explicitly when onboarding users to projects."],"tags":["permission","project","write-access"],"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"}