theonedev/onedev · error · UnauthorizedException

No permission to update issue fields

Error message

No permission to update issue fields

What it means

Thrown as UnauthorizedException when editIssue still has remaining non-empty data fields after handling state/iterations etc., but the subject lacks the permission to edit issue fields on that issue (SecurityUtils.canEditIssueFields). OneDev refuses to apply arbitrary field changes from a user without field-edit rights.

Source

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

        @SuppressWarnings("unchecked")
        List<String> iterationNames = (List<String>) data.remove("iterations");
        if (iterationNames != null) {
            if (!SecurityUtils.canScheduleIssues(subject, issue.getProject()))
                throw new UnauthorizedException("Issue schedule permission required to set iterations");
            var iterations = new ArrayList<Iteration>();
            for (var iterationName : iterationNames) {
                var iteration = iterationService.findInHierarchy(issue.getProject(), iterationName);
                if (iteration == null)
                    throw new NotFoundException("Iteration '" + iterationName + "' not found");
                iterations.add(iteration);
            }
            issueChangeService.changeIterations(user, issue, iterations);
        }

        if (!data.isEmpty()) {
            if (!SecurityUtils.canEditIssueFields(subject, issue)) 
                throw new UnauthorizedException("No permission to update issue fields");

            issueChangeService.changeFields(user, issue, FieldUtils.getFieldValues(subject, issue.getProject(), data));
        }

        return IssueHelper.getDetail(currentProject, issue);
    }

    @Path("/change-issue-state")
    @POST
    public Map<String, Object> changeIssueState(
                @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();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Grant the user permission to edit issue fields (e.g., 'Edit Issue' / appropriate role) on the project.
  2. Perform the field update as a user with edit rights.
  3. Remove the extra fields from the request if only state/iterations changes were intended.

Example fix

// before
Map<String, Serializable> data = Map.of("priority", "High"); // user can't edit fields
// after: use an account with field-edit permission or omit the field
Map<String, Serializable> data = Map.of();
Defensive patterns

Strategy: try-catch

Validate before calling

// only include data keys the user is allowed to edit
const editable = canEditIssueFields(user, issue);
if (!editable && Object.keys(data).length > 0) {
  throw new Error("User cannot edit issue fields; dropping field updates");
}

Type guard

function canEditFields(user, issue) {
  return issue.permissions?.editFields === true;
}

Try / catch

try {
  await editIssue(project, ref, data);
} catch (e) {
  if (e.status === 401 || /No permission to update issue fields/.test(e.message)) {
    // retry with a privileged identity or report to the caller
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the AI tod editIssue endpoint with any remaining keys in the data map (custom fields, etc.) while the authenticated user cannot edit issue fields for the issue (e.g., not issue author, reporter, editor, or project manager per project issue permission settings).

Common situations: Low-privileged user tries to edit custom fields; AI agent operates on behalf of a read-mostly user; project restricts field editing to specific roles.

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