theonedev/onedev · error · NotAcceptableException

Pull request is closed

Error message

Pull request is closed

What it means

The endpoint refuses to change the merge strategy of a pull request that is no longer open (merged or discarded). request.isOpen() is checked before pullRequestChangeService.changeMergeStrategy() runs, and a NotAcceptableException is thrown when the check fails.

Source

Thrown at server-core/src/main/java/io/onedev/server/ai/TodResource.java:1355

        if (title != null) 
            pullRequestChangeService.changeTitle(user, request, title);

        if (data.containsKey("description")) 
            pullRequestChangeService.changeDescription(user, request, (String) data.remove("description"));

        var labelNames = (List<String>) data.remove("labels");
        if (labelNames != null) {
            try {
                pullRequestLabelService.sync(request, labelNames);
            } catch (EntityNotFoundException e) {
                throw new NotFoundException(e.getMessage());
            }
        }

        var mergeStrategyName = (String) data.remove("mergeStrategy");
        if (mergeStrategyName != null) {
            if (!request.isOpen())
                throw new NotAcceptableException("Pull request is closed");
            pullRequestChangeService.changeMergeStrategy(user, request, MergeStrategy.valueOf(mergeStrategyName));
        }

        var assigneeNames = (List<String>) data.remove("assignees");
        if (assigneeNames != null) {                        
            if (!request.isOpen())
                throw new NotAcceptableException("Pull request is closed");
            for (var assigneeName : assigneeNames) {
                User assignee = userService.findByName(assigneeName);
                if (assignee == null)
                    throw new NotFoundException("Assignee not found: " + assigneeName);
                if (request.getAssignments().stream().noneMatch(it -> it.getUser().equals(assignee))) {
                    PullRequestAssignment assignment = new PullRequestAssignment();
                    assignment.setRequest(request);
                    assignment.setUser(assignee);
                    pullRequestAssignmentService.create(assignment);
                }
            }

View on GitHub (pinned to d44925c47c)

Solutions

  1. Re-fetch the pull request and confirm it is open before sending 'mergeStrategy'.
  2. If the PR is already merged, the merge strategy is moot — drop the field from the request.
  3. If the PR was discarded, reopen it (if possible) before changing the merge strategy.
  4. Make editing workflows optimistic: handle 406/NotAcceptable responses by refreshing state and retrying only relevant fields.

Example fix

// before
// blindly POST mergeStrategy after long processing
// after
if (pullRequest.state === 'open') {
  await editPullRequest({ mergeStrategy: 'SQUASH' });
} else {
  // skip strategy change; PR closed
}
Defensive patterns

Strategy: validation

Validate before calling

const pr = await getPullRequest(ref);
if (pr.state !== 'open') throw new Error(`PR ${ref} is ${pr.state}; mergeStrategy cannot be changed`);

Type guard

function isEditableOpen(pr) { return pr && pr.state === 'open'; }

Try / catch

try {
  await editPullRequest(ref, { mergeStrategy: 'SQUASH' });
} catch (e) {
  if (e.status === 406 && e.message.includes('closed')) {
    await refreshPullRequest(ref); // re-sync state and skip
  }
}

Prevention

When it happens

Trigger: POST /edit-pull-request with 'mergeStrategy' set on a pull request whose state is MERGED or DISCARDED.

Common situations: An automation or AI agent fetched the PR details, another user merged/closed it, then the agent submitted the mergeStrategy update; racing workflows that edit stale PR references.

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/cc66295c69fc6924. Report an issue: GitHub.