{"record":{"id":"d1027feb97b0c144","repo":"theonedev/onedev","slug":"assignee-should-have-code-write-permission","errorCode":null,"errorMessage":"Assignee should have code write permission: ","messagePattern":"Assignee should have code write permission: ","errorType":"http","errorClass":"NotAcceptableException","httpStatus":406,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/PullRequestResource.java","lineNumber":309,"sourceCode":"\t\t\t\tif (!SecurityUtils.canReadCode(request.getProject()))\n\t\t\t\t\tthrow new NotAcceptableException(\"Reviewer should have code read permission: \" + reviewer.getName());\n\n\t\t\t\tif (request.getReview(reviewer) == null) {\n\t\t\t\t\tPullRequestReview review = new PullRequestReview();\n\t\t\t\t\treview.setRequest(request);\n\t\t\t\t\treview.setUser(reviewer);\n\t\t\t\t\trequest.getReviews().add(review);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (data.getAssigneeIds() != null && !data.getAssigneeIds().isEmpty()) {\n\t\t\tfor (Long assigneeId : data.getAssigneeIds()) {\n\t\t\t\tPullRequestAssignment assignment = new PullRequestAssignment();\n\t\t\t\tassignment.setRequest(request);\n\t\t\t\tvar assignee = userService.load(assigneeId);\n\t\t\t\tif (!SecurityUtils.canWriteCode(request.getProject()))\n\t\t\t\t\tthrow new NotAcceptableException(\"Assignee should have code write permission: \" + assignee.getName());\n\t\t\t\tassignment.setUser(assignee);\n\t\t\t\trequest.getAssignments().add(assignment);\n\t\t\t}\n\t\t}\n\n\t\tpullRequestService.open(request);\n\n\t\treturn Response.ok(request.getId()).build();\n    }\n\t\n\t@Api(order=1300)\n\t@Path(\"/{requestId}/title\")\n    @POST\n    public Response setTitle(@PathParam(\"requestId\") Long requestId, @NotEmpty String title) {\n\t\tPullRequest request = pullRequestService.load(requestId);\n\t\tvar subject = SecurityUtils.getSubject();\n\t\tvar user = SecurityUtils.getUser(subject);\n    \tif (!SecurityUtils.canModifyPullRequest(subject, request))","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/PullRequestResource.java#L291-L327","documentation":"During PR creation, each id in assigneeIds is checked with SecurityUtils.canWriteCode on the project; if an assignee lacks code-write, a NotAcceptableException naming the assignee is thrown. OneDev requires assignees to be able to modify code since assignments imply work on the branch/code.","triggerScenarios":"POST /~api/pull-requests with assigneeIds containing read-only users or guests; assigning project outsiders; service accounts with read-only tokens as assignees.","commonSituations":"Default assignee templates including users downgraded to read access; assigning managers/QA who never had write permission; integrations that blindly copy assignees from issues.","solutions":["Remove non-writer users from assigneeIds.","Grant the intended assignee a role with code-write on the project.","Assign users who can push branches in the project.","Create PR without assignees and assign later via the UI once permissions are fixed."],"exampleFix":"// before\n{\"assigneeIds\":[8]}   // user 8 has only code-read\n// after: grant user 8 code-write on the project, or\n{\"assigneeIds\":[]}","handlingStrategy":"validation","validationCode":"const canWrite = await fetch(`/~api/projects/${projectId}/permissions`)\n// pass only assignees known to have write/code-write role on the project\nconst eligibleIds = assigneeIds.filter(id => writersByProject[projectId]?.includes(id))","typeGuard":null,"tryCatchPattern":"try {\n  await api.post('/pull-requests', {...data, assigneeIds})\n} catch (e) {\n  if (e.message?.startsWith('Assignee should have code write permission')) {\n    // drop the named assignee and retry, or report to user\n  } else throw e\n}","preventionTips":["Only auto-assign users with push/write access to the repo.","Re-check assignee permissions after role changes.","Prefer UI-validated assignment for read-only stakeholders (use watchers/comments instead).","Keep a cached project-writers list refreshed on membership changes."],"tags":["rest","validation","permissions","assignees"],"backgroundTag":"insufficient-permissions","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}