theonedev/onedev · error · NotAcceptableException

Pull request submitter cannot be reviewer

Error message

Pull request submitter cannot be reviewer

What it means

addReviewer rejects with NotAcceptableException 'Pull request submitter cannot be reviewer' when the userId being added is the pull request's own submitter. OneDev enforces this domain rule because a submitter reviewing their own changes is meaningless for the review workflow; the same rule exists in the REST create-PR path.

Source

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

    	if (!SecurityUtils.canModifyPullRequest(subject, request))
			throw new UnauthorizedException();
		pullRequestChangeService.changeDescription(user, request, description);
		return Response.ok().build();
    }

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

		var currentUser = SecurityUtils.getUser();
		if (!SecurityUtils.canModifyPullRequest(currentUser.asSubject(), request)) 
			throw new UnauthorizedException();

		if (user.equals(request.getSubmitter()))
			throw new NotAcceptableException("Pull request submitter cannot be reviewer");

		if (!SecurityUtils.canReadCode(user.asSubject(), request.getProject()))
			throw new NotAcceptableException("Reviewer needs to have read code permission to the project");
			
		var review = request.getReview(user);
		if (review != null) {
			if (review.getStatus() == EXCLUDED) {
				review.setStatus(PENDING);
				pullRequestReviewService.createOrUpdate(currentUser, review);
			}
		} else {
			review = new PullRequestReview();
			review.setRequest(request);
			review.setUser(user);
			review.setStatus(PENDING);

			pullRequestReviewService.createOrUpdate(currentUser, review);	
		}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Exclude the submitter's id from the reviewer list before calling.
  2. Filter participant-derived lists against request.submitterId.
  3. Add a guard in your automation: skip a user if user.id == request.submitter.id.
  4. Pick a different reviewer from the team.

Example fix

// before
curl -X PUT .../pull-requests/50/reviewers/7   // user 7 submitted PR 50 -> 406
// after
if (userId !== request.submitterId) {
  curl -X PUT .../pull-requests/50/reviewers/${userId}
}
Defensive patterns

Strategy: validation

Validate before calling

function eligibleReviewer(user, pullRequest) {
  return user.id !== pullRequest.submitterId && user.active && user.projectIds.includes(pullRequest.projectId)
}
// filter before PUT /reviewers/{userId}
if (!eligibleReviewer(candidate, pr)) return

Try / catch

try {
  await api.put(`/pull-requests/${id}/reviewers/${userId}`)
} catch (e) {
  if (e.status === 400 && e.message.includes('submitter cannot be reviewer')) return // already-handled rule
  throw e
}

Prevention

When it happens

Trigger: PUT /~api/pull-requests/{requestId}/reviewers/{userId} where userId equals request.submitter.id; scripts that build reviewer lists from participants without excluding the author; auto-assignment plugins not filtering the submitter.

Common situations: CODEOWNERS-like automation adding every mentioned user; bulk tools copying reviewers between PRs by the same author; tests using the same account for both submit and review.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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