theonedev/onedev · error · UnauthorizedException

No permission to update issue title

Error message

No permission to update issue title

What it means

editIssue allows changing the title only if SecurityUtils.canModifyIssue(subject, issue) is true; otherwise it throws UnauthorizedException with "No permission to update issue title". This is a per-issue authorization check (considers project roles and issue-level permissions like confidential issues), not an authentication problem.

Source

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

                @QueryParam("currentProject") @NotNull String currentProjectPath, 
                @QueryParam("reference") @NotNull String issueReference, 
                @NotNull Map<String, Serializable> data) {
        var subject = SecurityUtils.getSubject();
        var user = SecurityUtils.getUser(subject);

        if (user == null)
            throw new UnauthenticatedException();

        var currentProject = getProject(currentProjectPath);

        var issue = getIssue(currentProject, issueReference);

        IssueHelper.normalizeData(data);

        var title = (String) data.remove("title");
        if (title != null) { 
            if (!SecurityUtils.canModifyIssue(subject, issue))
                throw new UnauthorizedException("No permission to update issue title");
            issueChangeService.changeTitle(user, issue, title);
        }

        if (data.containsKey("description")) {
            if (!SecurityUtils.canModifyIssue(subject, issue))
                throw new UnauthorizedException("No permission to update issue description");
            issueChangeService.changeDescription(user, issue, (String) data.remove("description"));
        }

        var confidential = (Boolean) data.remove("confidential");
        if (confidential != null) {
            if (!SecurityUtils.canModifyIssue(subject, issue))
                throw new UnauthorizedException("No permission to update issue confidential");
            issueChangeService.changeConfidential(user, issue, confidential);
        }

        Integer ownEstimatedTime = (Integer) data.remove("ownEstimatedTime");
        if (ownEstimatedTime != null) {

View on GitHub (pinned to d44925c47c)

Solutions

  1. Remove the "title" key from the request data if only viewing permission is available, or request project permission that allows issue modification.
  2. Ask a project admin to grant the user Edit Issue access on the project (or the specific confidential issue).
  3. Verify the issue isn't confidential for this user; if it must be edited, use an account with the necessary role.
  4. Test with a user who can edit the issue in the web UI to confirm the permission model, then align API usage.

Example fix

// before
editIssue(project, ref, {title: "New title", description: "x"}) // no modify perm
// after
editIssue(project, ref, {description: "x"}) // only fields user may change
Defensive patterns

Strategy: validation

Validate before calling

// only include fields the user may change
const canEdit = issueDetail.permission && issueDetail.permission.modify;
const payload = canEdit ? {title} : {};
if (title !== undefined && !canEdit) throw new Error('Skipping title change: no modify permission');

Try / catch

try { await editIssue(project, ref, {title}); } catch (e) { if (e.status === 403 && /title/.test(e.message)) { notifyAdmin('Grant Edit Issue permission'); } else throw e; }

Prevention

When it happens

Trigger: Including the "title" key in the data map passed to POST /edit-issue while the authenticated user lacks modify permission on that issue (e.g. read-only role, confidential issue, non-member of the project).

Common situations: AI assistants auto-generating edits on issues the user can only view; service tokens of accounts with Reporter-only access; editing a confidential issue as an outsider.

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