{"record":{"id":"1714bee5b4c1f8eb","repo":"theonedev/onedev","slug":"cannot-delete-pull-request-request-getreference","errorCode":null,"errorMessage":"Cannot delete pull request \"${request.getReference().toString(request.getProject())}\" as it has workspaces","messagePattern":"Cannot delete pull request \"(.+?)\" as it has workspaces","errorType":"validation","errorClass":"NotAcceptableException","httpStatus":400,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/service/impl/DefaultPullRequestService.java","lineNumber":234,"sourceCode":"\t\t\tnumberGenerator = new SequenceGenerator(PullRequest.class, clusterService, dao);\n\t\treturn numberGenerator;\n\t}\n\n\tpublic Object writeReplace() throws ObjectStreamException {\n\t\treturn new ManagedSerializedForm(PullRequestService.class);\n\t}\n\n\t@Transactional\n\t@Override\n\tpublic void delete(PullRequest request) {\n\t\tcheckNoWorkspaces(request);\n\t\tdoDelete(request);\n\t\tlistenerRegistry.post(new PullRequestDeleted(request));\n\t}\n\n\tprivate void checkNoWorkspaces(PullRequest request) {\n\t\tif (request.getWorkspaces().size() > 0) {\n\t\t\tthrow new NotAcceptableException(\"Cannot delete pull request \\\"\"\n\t\t\t\t\t+ request.getReference().toString(request.getProject()) + \"\\\" as it has workspaces\");\n\t\t}\n\t}\n\n\tprivate void doDelete(PullRequest request) {\n\t\tCollection<String> refs = Lists.newArrayList(\n\t\t\t\trequest.getHeadRef(), request.getMergeRef(), request.getBaseRef(), request.getBuildRef());\n\t\tfor (PullRequestUpdate update: request.getUpdates())\n\t\t\trefs.add(update.getHeadRef());\n\n\t\tgitService.deleteRefs(request.getTargetProject(), refs);\n\n    \tQuery<?> query = getSession().createQuery(String.format(\n    \t\t\t\"update CodeComment set %s=null where %s=:request\",\n    \t\t\tCodeComment.PROP_COMPARE_CONTEXT + \".\" + CompareContext.PROP_PULL_REQUEST,\n    \t\t\tCodeComment.PROP_COMPARE_CONTEXT + \".\" + CompareContext.PROP_PULL_REQUEST));\n    \tquery.setParameter(\"request\", request);\n    \tquery.executeUpdate();","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/service/impl/DefaultPullRequestService.java#L216-L252","documentation":"OneDev refuses to delete a pull request that still has linked code workspaces (dev environments attached to the PR). checkNoWorkspaces throws this NotAcceptableException before doDelete to avoid orphaning active workspace instances. The PR reference is included in the message for context.","triggerScenarios":"Calling DefaultPullRequestService.delete(request) (directly or via REST DELETE) while request.getWorkspaces().size() > 0 — i.e. at least one workspace created from the PR still exists.","commonSituations":"Cleaning up old PRs while developers still have dev environments open from them; automated cleanup scripts hitting PRs whose workspaces were never torn down; project admin bulk-deleting stale PRs.","solutions":["Delete or terminate the PR's workspaces first, then retry the delete","If workspaces are stale, clean them up (workspace service / admin UI) before deleting the PR","Check request.getWorkspaces().isEmpty() before calling delete"],"exampleFix":"// before\nprService.delete(request); // fails while workspaces exist\n// after\nif (request.getWorkspaces().isEmpty())\n    prService.delete(request);\nelse\n    request.getWorkspaces().forEach(workspaceService::delete);","handlingStrategy":"validation","validationCode":"if (!request.getWorkspaces().isEmpty())\n    throw new IllegalStateException(\"delete PR first requires removing its workspaces\");","typeGuard":null,"tryCatchPattern":"try {\n    prService.delete(request);\n} catch (NotAcceptableException e) {\n    // surface that workspaces must be deleted first\n}","preventionTips":["Tear down PR workspaces as part of PR lifecycle automation","Check getWorkspaces().isEmpty() before delete","Schedule cleanup of stale workspaces"],"tags":["pull-request","delete","workspaces","precondition"],"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-14T00:17:10.932Z"}