{"record":{"id":"62ba5a8417cad4e9","repo":"theonedev/onedev","slug":"another-pull-request-already-opened-for-this-chang","errorCode":null,"errorMessage":"Another pull request already opened for this change","messagePattern":"Another pull request already opened for this change","errorType":"validation","errorClass":"NotAcceptableException","httpStatus":400,"severity":"warning","filePath":"server-core/src/main/java/io/onedev/server/service/impl/DefaultPullRequestService.java","lineNumber":440,"sourceCode":"\n\t@Transactional\n\t@Override\n\tpublic void open(PullRequest request) {\n\t\tPreconditions.checkArgument(request.isNew());\n\n\t\tvar target = Preconditions.checkNotNull(request.getTarget(),\n\t\t\t\t\"Pull request target must be set before calling open\");\n\t\tvar source = Preconditions.checkNotNull(request.getSource(),\n\t\t\t\t\"Pull request source must be set before calling open\");\n\t\tPreconditions.checkNotNull(request.getSubmitter(),\n\t\t\t\t\"Pull request submitter must be set before calling open\");\n\n\t\tif (target.equals(source))\n\t\t\tthrow new NotAcceptableException(\"Source and target are the same\");\n\n\t\tPullRequest existing = findOpen(target, source);\n\t\tif (existing != null)\n\t\t\tthrow new NotAcceptableException(\"Another pull request already opened for this change\");\n\n\t\texisting = findEffective(target, source);\n\t\tif (existing != null) {\n\t\t\tif (existing.isOpen())\n\t\t\t\tthrow new NotAcceptableException(\"Another pull request already opened for this change\");\n\t\t\telse\n\t\t\t\tthrow new NotAcceptableException(\"Another pull request already merged the change\");\n\t\t}\n\n\t\tif (request.getBaseCommitHash() == null) {\n\t\t\tObjectId baseCommitId = gitService.getMergeBase(\n\t\t\t\t\ttarget.getProject(), target.getObjectId(),\n\t\t\t\t\tsource.getProject(), source.getObjectId());\n\t\t\tif (baseCommitId == null)\n\t\t\t\tthrow new NotAcceptableException(\"No common base for target and source\");\n\t\t\trequest.setBaseCommitHash(baseCommitId.name());\n\t\t}\n","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/service/impl/DefaultPullRequestService.java#L422-L458","documentation":"OneDev's DefaultPullRequestService.open() refuses to create a pull request when an open pull request already exists for the same target<-source branch pair. findOpen() is consulted first; if it returns a live PR, a NotAcceptableException (HTTP 406) is thrown because duplicate PRs for the same change would fragment review and merge state.","triggerScenarios":"Calling PullRequestService.open() (directly or via the 'new pull request' flow) when findOpen(target, source) returns a non-null PullRequest, i.e. an open PR with the exact same target and source branches already exists.","commonSituations":"Double-submitting the PR creation form after a page reload; scripting PR creation in CI that runs on every push without checking for an existing PR; two users creating the same PR concurrently.","solutions":["Check findOpen()/list the project's open pull requests before calling open() and reuse the existing PR instead","Catch NotAcceptableException from open() and look up the existing PR to return its number/link to the user","Make automated PR creation idempotent: key scripts on the target/source branch pair and skip creation if one exists","If the existing PR is stale/wrong, close it first, then open the new one"],"exampleFix":"// before\npullRequestService.open(pullRequest); // throws if one already exists\n// after\nPullRequest existing = pullRequestService.findOpen(target, source);\nif (existing == null)\n    pullRequestService.open(pullRequest);\nelse\n    logger.info(\"Reusing existing PR #{}\", existing.getNumber());","handlingStrategy":"validation","validationCode":"PullRequest existing = pullRequestService.findOpen(target, source);\nif (existing != null)\n    return existing; // reuse instead of opening","typeGuard":null,"tryCatchPattern":"try {\n    pullRequestService.open(request);\n} catch (NotAcceptableException e) {\n    if (e.getMessage().contains(\"Another pull request already opened\")) {\n        PullRequest existing = pullRequestService.findOpen(target, source);\n        redirect(existing);\n    } else throw e;\n}","preventionTips":["Always call findOpen()/findEffective before opening a PR","Make automated PR creation idempotent per (target, source) pair","Debounce double-submits in the UI"],"tags":["pull-request","duplicate-resource","http-406","onedev"],"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"}