{"record":{"id":"c7f84db6b9fa6a09","repo":"theonedev/onedev","slug":"code-read-permission-required-to-query-pull-reques","errorCode":null,"errorMessage":"Code read permission required to query pull requests","messagePattern":"Code read permission required to query pull requests","errorType":"http","errorClass":"UnauthorizedException","httpStatus":403,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/ai/TodResource.java","lineNumber":800,"sourceCode":"        return workMap;\n    }\n\n    @Path(\"/query-pull-requests\")\n    @GET\n    public List<Map<String, Object>> queryPullRequests(\n                @QueryParam(\"currentProject\") @NotNull String currentProjectPath, \n                @QueryParam(\"project\") String projectPath, \n                @QueryParam(\"query\") String query, \n                @QueryParam(\"offset\") int offset, \n                @QueryParam(\"count\") int count) {\n        var subject = SecurityUtils.getSubject();\n        if (SecurityUtils.getUser(subject) == null)\n            throw new UnauthenticatedException();\n\n        var projectContext = getProjectContext(projectPath, currentProjectPath);\n\n        if (!SecurityUtils.canReadCode(projectContext.project))\n            throw new UnauthorizedException(\"Code read permission required to query pull requests\");\n\n        if (count > RestConstants.MAX_PAGE_SIZE)\n            throw new NotAcceptableException(\"Count should not be greater than \" + RestConstants.MAX_PAGE_SIZE);\n\n        EntityQuery<PullRequest> parsedQuery;\n        if (query != null) \n            parsedQuery = PullRequestQuery.parse(projectContext.project, query, true);\n        else\n            parsedQuery = new PullRequestQuery();\n\n        var summaries = new ArrayList<Map<String, Object>>();\n        for (var pullRequest : pullRequestService.query(subject, projectContext.project, parsedQuery, false, offset, count)) {\n            var summary = PullRequestHelper.getSummary(projectContext.currentProject, pullRequest, false);\n            summary.put(\"link\", urlService.urlFor(pullRequest, true));\n            summaries.add(summary);\n        }\n        return summaries;\n    }","sourceCodeStart":782,"sourceCodeEnd":818,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/ai/TodResource.java#L782-L818","documentation":"GET /query-pull-requests in TodResource throws UnauthorizedException when SecurityUtils.canReadCode(projectContext.project) is false. Querying pull requests requires code read permission on the project; the authenticated user lacks it.","triggerScenarios":"Calling query-pull-requests for a project where the user has no role granting code read (e.g. Issue Reporter-only role), or the resolved project (from 'project' or 'currentProject' param) is private to other users.","commonSituations":"AI agent running as a user with limited project roles; querying pull requests of another project passed via the 'project' query param; guest/anonymous-restricted accounts; project ACL changed recently.","solutions":["Grant the user a project role with code read permission (Project > Access Control)","Query pull requests only in projects the calling user can read code in","Check the 'project'/'currentProject' query params resolve to the intended project","Use a token of a user with at least Developer role in the target project"],"exampleFix":"// before: role 'Reader (issues only)' in project 'app' -> query-pull-requests fails\n// after: Project app > Access Control > change role to 'Developer' (code read included)","handlingStrategy":"validation","validationCode":"const project = await getProject(projectPath ?? currentProject); if (!project.permissions?.canReadCode) throw new Error('Code read permission required to query pull requests on ' + projectPath);","typeGuard":null,"tryCatchPattern":"try { await queryPullRequests(params); } catch (e) { if (e.status === 403 || /code read permission/i.test(e.message)) useAccountWithCodeRead(); else throw e; }","preventionTips":["Give agent accounts at least code-read roles in target projects","Resolve which project (project vs currentProject param) is queried and check its ACL","Re-check permissions after project role changes","Keep AI agent tokens scoped to users with needed project access"],"tags":["permissions","pull-requests","authorization"],"backgroundTag":"permission-denied","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"}