{"record":{"id":"ae0b543cf2e1f8aa","repo":"theonedev/onedev","slug":"this-reviewer-is-mandatory-and-cannot-be-removed","errorCode":null,"errorMessage":"This reviewer is mandatory and cannot be removed","messagePattern":"This reviewer is mandatory and cannot be removed","errorType":"http","errorClass":"NotAcceptableException","httpStatus":406,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/PullRequestResource.java","lineNumber":430,"sourceCode":"\n\t@Api(order=1475)\n\t@Path(\"/{requestId}/reviewers/{userId}\")\n\t@DELETE\n\tpublic Response removeReviewer(@PathParam(\"requestId\") Long requestId, @PathParam(\"userId\") Long userId) {\t\t\n\t\tvar request = pullRequestService.load(requestId);\n\t\tvar user = userService.load(userId);\n\n\t\tvar subject = SecurityUtils.getSubject();\n\t\t\n\t\tif (!SecurityUtils.canModifyPullRequest(subject, request))\n\t\t\tthrow new UnauthorizedException();\n\n\t\tvar review = request.getReview(user);\n\t\tif (review != null) {\n\t\t\treview.setStatus(EXCLUDED);\n\t\t\tpullRequestService.checkReviews(request, false);\n\t\t\tif (review.getStatus() != EXCLUDED) \n\t\t\t\tthrow new NotAcceptableException(\"This reviewer is mandatory and cannot be removed\");\n\t\t\tpullRequestReviewService.createOrUpdate(user, review);\n\t\t}\n\n\t\treturn Response.ok().build();\t\n\t}\n\n\t@Api(order=1480)\n\t@Path(\"/{requestId}/assignees/{userId}\")\n\t@POST\n\tpublic Response addAssignee(@PathParam(\"requestId\") Long requestId, @PathParam(\"userId\") Long userId) {\n\t\tvar request = pullRequestService.load(requestId);\n\t\tvar user = userService.load(userId);\n\n\t\tif (!SecurityUtils.canModifyPullRequest(request))\n\t\t\tthrow new UnauthorizedException();\n\n\t\tif (!SecurityUtils.canWriteCode(user.asSubject(), request.getProject()))\n\t\t\tthrow new NotAcceptableException(\"Assignee needs to have write code permission to the project\");","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/PullRequestResource.java#L412-L448","documentation":"NotAcceptableException (HTTP 400) thrown when removing a reviewer whose review cannot actually be excluded. The code sets the review to EXCLUDED then calls checkReviews; if the review's status is re-evaluated back to non-EXCLUDED (because the reviewer is mandated by the project's review requirement, e.g. required reviewer policy), the API refuses the removal.","triggerScenarios":"DELETE /pull-requests/{requestId}/reviewers/{userId} where the reviewer is designated mandatory by the project's pull request review settings (required reviewers), so checkReviews restores the status after EXCLUDED is set.","commonSituations":"Project policy requires sign-off from specific users/teams; admin template marks reviewers as required; caller assumes any reviewer is removable but project rules say otherwise.","solutions":["Change the project's pull request review requirement to make the reviewer optional before removing them.","Ask the project admin to adjust the mandatory-reviewer policy.","Remove a different, non-mandatory reviewer instead."],"exampleFix":"// before: DELETE .../pull-requests/42/reviewers/7 -> 400 mandatory reviewer\n// after (admin): set Project > Pull Requests > Review Requirements so user 7 is no longer required,\n// then DELETE .../pull-requests/42/reviewers/7 -> 200 OK","handlingStrategy":"try-catch","validationCode":"// Check the project's review requirements before attempting removal\nconst requirements = await api.getProjectReviewRequirements(projectId);\nif (requirements.requiredReviewerIds.includes(userId)) {\n  throw new Error(`Reviewer ${userId} is mandated by project policy; adjust requirements first`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.removeReviewer(requestId, userId);\n} catch (e) {\n  if (e.status === 400 && /mandatory/.test(e.body)) {\n    // update project review requirements, or pick another reviewer\n  } else throw e;\n}","preventionTips":["Review project pull-request review policies before removing reviewers","Treat 'mandatory reviewer' as a project-level config, not a per-PR state","Surface policy info in tooling that manages reviewers"],"tags":["pull-request","code-review","policy"],"backgroundTag":"invalid-state-transition","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"}