theonedev/onedev · error · NotAcceptableException

This reviewer is mandatory and cannot be removed

Error message

This reviewer is mandatory and cannot be removed

What it means

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.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/PullRequestResource.java:430

	@Api(order=1475)
	@Path("/{requestId}/reviewers/{userId}")
	@DELETE
	public Response removeReviewer(@PathParam("requestId") Long requestId, @PathParam("userId") Long userId) {		
		var request = pullRequestService.load(requestId);
		var user = userService.load(userId);

		var subject = SecurityUtils.getSubject();
		
		if (!SecurityUtils.canModifyPullRequest(subject, request))
			throw new UnauthorizedException();

		var review = request.getReview(user);
		if (review != null) {
			review.setStatus(EXCLUDED);
			pullRequestService.checkReviews(request, false);
			if (review.getStatus() != EXCLUDED) 
				throw new NotAcceptableException("This reviewer is mandatory and cannot be removed");
			pullRequestReviewService.createOrUpdate(user, review);
		}

		return Response.ok().build();	
	}

	@Api(order=1480)
	@Path("/{requestId}/assignees/{userId}")
	@POST
	public Response addAssignee(@PathParam("requestId") Long requestId, @PathParam("userId") Long userId) {
		var request = pullRequestService.load(requestId);
		var user = userService.load(userId);

		if (!SecurityUtils.canModifyPullRequest(request))
			throw new UnauthorizedException();

		if (!SecurityUtils.canWriteCode(user.asSubject(), request.getProject()))
			throw new NotAcceptableException("Assignee needs to have write code permission to the project");

View on GitHub (pinned to d44925c47c)

Solutions

  1. Change the project's pull request review requirement to make the reviewer optional before removing them.
  2. Ask the project admin to adjust the mandatory-reviewer policy.
  3. Remove a different, non-mandatory reviewer instead.

Example fix

// before: DELETE .../pull-requests/42/reviewers/7 -> 400 mandatory reviewer
// after (admin): set Project > Pull Requests > Review Requirements so user 7 is no longer required,
// then DELETE .../pull-requests/42/reviewers/7 -> 200 OK
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the project's review requirements before attempting removal
const requirements = await api.getProjectReviewRequirements(projectId);
if (requirements.requiredReviewerIds.includes(userId)) {
  throw new Error(`Reviewer ${userId} is mandated by project policy; adjust requirements first`);
}

Try / catch

try {
  await api.removeReviewer(requestId, userId);
} catch (e) {
  if (e.status === 400 && /mandatory/.test(e.body)) {
    // update project review requirements, or pick another reviewer
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/ae0b543cf2e1f8aa. Report an issue: GitHub.