theonedev/onedev · error · UnauthorizedException

Issue schedule permission required to set iterations

Error message

Issue schedule permission required to set iterations

What it means

Adding the issue to iterations also requires schedule-issues permission. When the data map contains "iterations" and SecurityUtils.canScheduleIssues(subject, project) is false, createIssue throws UnauthorizedException.

Source

Thrown at server-core/src/main/java/io/onedev/server/ai/IssueHelper.java:298

        if (confidential != null)
            issue.setConfidential(confidential);

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

        List<String> iterationNames = (List<String>) data.remove("iterations");
        if (iterationNames != null) {
            if (!SecurityUtils.canScheduleIssues(subject, project))
                throw new UnauthorizedException("Issue schedule permission required to set iterations");
            var iterationService = OneDev.getInstance(IterationService.class);
            for (var iterationName : iterationNames) {
                var iteration = iterationService.findInHierarchy(project, iterationName);
                if (iteration == null)
                    throw new ExplicitException("Iteration '" + iterationName + "' not found");
                IssueSchedule schedule = new IssueSchedule();
                schedule.setIssue(issue);
                schedule.setIteration(iteration);
                issue.getSchedules().add(schedule);
            }
        }

        issue.setProject(project);
        issue.setSubmitDate(new Date());
        issue.setSubmitter(SecurityUtils.getUser(subject));
        issue.setState(issueSetting.getInitialStateSpec().getName());

        issue.setFieldValues(FieldUtils.getFieldValues(subject, project, data));

View on GitHub (pinned to d44925c47c)

Solutions

  1. Grant 'Schedule issues' permission to the acting user's role on the project
  2. Run the automation with an account that has schedule permission
  3. Omit "iterations" (schedule them later with a permitted account)

Example fix

// before
data.put("iterations", List.of("Sprint 12"));
// after
if (SecurityUtils.canScheduleIssues(subject, project)) data.put("iterations", List.of("Sprint 12"));
Defensive patterns

Strategy: validation

Validate before calling

if (data.containsKey("iterations")
        && !SecurityUtils.canScheduleIssues(subject, project))
    throw new SecurityException("Actor lacks schedule-issues permission");

Try / catch

try {
    issueHelper.createIssue(project, subject, data);
} catch (UnauthorizedException e) {
    if (e.getMessage().contains("iterations")) {
        // create issue without schedules, or rerun with a permitted account
    }
}

Prevention

When it happens

Trigger: createIssue called with a non-null "iterations" list while the subject lacks issue-schedule permission on the project.

Common situations: Automation running as a user without scheduling rights; AI tool calls acting on behalf of read/report-level users; recently tightened project role permissions.

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