theonedev/onedev · error · UnauthorizedException

Code read permission required to query pull requests

Error message

Code read permission required to query pull requests

What it means

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.

Source

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

        return workMap;
    }

    @Path("/query-pull-requests")
    @GET
    public List<Map<String, Object>> queryPullRequests(
                @QueryParam("currentProject") @NotNull String currentProjectPath, 
                @QueryParam("project") String projectPath, 
                @QueryParam("query") String query, 
                @QueryParam("offset") int offset, 
                @QueryParam("count") int count) {
        var subject = SecurityUtils.getSubject();
        if (SecurityUtils.getUser(subject) == null)
            throw new UnauthenticatedException();

        var projectContext = getProjectContext(projectPath, currentProjectPath);

        if (!SecurityUtils.canReadCode(projectContext.project))
            throw new UnauthorizedException("Code read permission required to query pull requests");

        if (count > RestConstants.MAX_PAGE_SIZE)
            throw new NotAcceptableException("Count should not be greater than " + RestConstants.MAX_PAGE_SIZE);

        EntityQuery<PullRequest> parsedQuery;
        if (query != null) 
            parsedQuery = PullRequestQuery.parse(projectContext.project, query, true);
        else
            parsedQuery = new PullRequestQuery();

        var summaries = new ArrayList<Map<String, Object>>();
        for (var pullRequest : pullRequestService.query(subject, projectContext.project, parsedQuery, false, offset, count)) {
            var summary = PullRequestHelper.getSummary(projectContext.currentProject, pullRequest, false);
            summary.put("link", urlService.urlFor(pullRequest, true));
            summaries.add(summary);
        }
        return summaries;
    }

View on GitHub (pinned to d44925c47c)

Solutions

  1. Grant the user a project role with code read permission (Project > Access Control)
  2. Query pull requests only in projects the calling user can read code in
  3. Check the 'project'/'currentProject' query params resolve to the intended project
  4. Use a token of a user with at least Developer role in the target project

Example fix

// before: role 'Reader (issues only)' in project 'app' -> query-pull-requests fails
// after: Project app > Access Control > change role to 'Developer' (code read included)
Defensive patterns

Strategy: validation

Validate before calling

const project = await getProject(projectPath ?? currentProject); if (!project.permissions?.canReadCode) throw new Error('Code read permission required to query pull requests on ' + projectPath);

Try / catch

try { await queryPullRequests(params); } catch (e) { if (e.status === 403 || /code read permission/i.test(e.message)) useAccountWithCodeRead(); else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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