theonedev/onedev · error · UnauthorizedException

Issue schedule permission required to set iterations

Error message

Issue schedule permission required to set iterations

What it means

OneDev's AI tod resource throws UnauthorizedException when an agent attempts to set an issue's 'iterations' field via editIssue without the 'Schedule Issues' permission on the issue's project. The check runs via SecurityUtils.canScheduleIssues before any iteration lookup happens, so the request is rejected outright.

Source

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

            issueChangeService.changeConfidential(user, issue, confidential);
        }

        Integer ownEstimatedTime = (Integer) data.remove("ownEstimatedTime");
        if (ownEstimatedTime != null) {
            if (!subscriptionService.isSubscriptionActive())
                throw new NotAcceptableException("An active subscription is required for this feature");
            if (!issue.getProject().isTimeTracking())
                throw new NotAcceptableException("Time tracking needs to be enabled for the project");
            if (!SecurityUtils.canScheduleIssues(subject, issue.getProject()))
                throw new UnauthorizedException("Issue schedule permission required to set own estimated time");
            issueChangeService.changeOwnEstimatedTime(user, issue, ownEstimatedTime*60);
        }

        @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);

View on GitHub (pinned to d44925c47c)

Solutions

  1. Grant the user (or their group) the 'Schedule Issues' permission in the project's or organization's role settings.
  2. Use an authenticated identity that has scheduling rights on the project.
  3. Remove the 'iterations' key from the request data and change iterations through the regular UI/API with a permitted account.

Example fix

// before (client sends iterations as underprivileged user)
data.put("iterations", List.of("Sprint 1"));
// after: authenticate as a user with Schedule Issues permission, or drop the key
if (SecurityUtils.canScheduleIssues(subject, project)) {
    data.put("iterations", List.of("Sprint 1"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// client-side check before calling editIssue with 'iterations'
if (!userPermissions.includes("Schedule Issues")) {
    throw new Error("Skipping iterations update: schedule permission missing");
}

Type guard

function canSchedule(user, project) {
  return Boolean(user?.projects?.[project]?.permissions?.includes("Schedule Issues"));
}

Try / catch

try {
  await editIssue(project, ref, { iterations: ["Sprint 1"] });
} catch (e) {
  if (e.status === 401 || /schedule permission/i.test(e.message)) {
    // fall back to a permitted identity or skip iteration changes
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the AI tod editIssue endpoint (TodResource.editIssue) with an 'iterations' key in the data map while the authenticated subject lacks issue schedule permission on the target project.

Common situations: AI agent acting as a user who can edit issue fields but not manage schedules; project where only project owners/managers have Schedule Issues; permission recently revoked from the user.

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