theonedev/onedev · error · UnauthorizedException

No permission to write code in issue project

Error message

No permission to write code in issue project

What it means

getIssueDetail throws UnauthorizedException with this message when the caller passes forWrite=true but the authenticated user cannot write code in the issue's project (SecurityUtils.canWriteCode fails). Write-oriented AI operations are restricted to users with commit/write access.

Source

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

            throw new NotFoundException("Issue not found: " + referenceString);
        }
    }
    
    @Path("/get-issue")
    @GET
    public Map<String, Object> getIssueDetail(
                @QueryParam("currentProject") @NotNull String currentProjectPath, 
                @QueryParam("reference") @NotNull String issueReference, 
                @QueryParam("forWrite") Boolean forWrite) {
        var subject = SecurityUtils.getSubject();
        if (SecurityUtils.getUser(subject) == null)
            throw new UnauthenticatedException();

        var currentProject = getProject(currentProjectPath);
        var issue = getIssue(currentProject, issueReference);                

        if (forWrite != null && forWrite &&!SecurityUtils.canWriteCode(issue.getProject()))
            throw new UnauthorizedException("No permission to write code in issue project");

        return IssueHelper.getDetail(currentProject, issue);
    }

    @Path("/query-projects")
    @GET
    public List<Map<String, Object>> queryProjects(
                @QueryParam("query") String query,
                @QueryParam("offset") int offset,
                @QueryParam("count") int count) {
        var subject = SecurityUtils.getSubject();
        if (SecurityUtils.getUser(subject) == null)
            throw new UnauthenticatedException();

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

        var parsedQuery = ProjectQuery.parse(query);

View on GitHub (pinned to d44925c47c)

Solutions

  1. Call with forWrite=false (or omit) if only read access is needed.
  2. Grant the user (or token owner) a role with code-write permission in the issue's project.
  3. Use an access token from a user who is a committer/maintainer in that project.

Example fix

// before
GET /api/tod/get-issue?currentProject=p&reference=p#1&forWrite=true
// after (read-only)
GET /api/tod/get-issue?currentProject=p&reference=p#1&forWrite=false
Defensive patterns

Strategy: validation

Validate before calling

// only request write when the user actually has code-write access
const forWrite = needsWrite && userCanWriteCode(issueProject, currentUser);
const params = { currentProject, reference, forWrite };

Try / catch

try {
  return await getIssueDetail(params);
} catch (e) {
  if (isUnauthorizedError(e) && /write code/.test(e.message)) {
    return getIssueDetail({ ...params, forWrite: false });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling GET /get-issue with forWrite=true where the authenticated user's role in issue.getProject() lacks code-write permission.

Common situations: An AI agent requesting write access for a user who is only a reader; using a read-only CI/service token; user recently downgraded to a role without write access.

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