{"record":{"id":"1bfe7edc821496ee","repo":"theonedev/onedev","slug":"issue-schedule-permission-required-to-set-iteratio","errorCode":null,"errorMessage":"Issue schedule permission required to set iterations","messagePattern":"Issue schedule permission required to set iterations","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/ai/IssueHelper.java","lineNumber":298,"sourceCode":"        if (confidential != null)\n            issue.setConfidential(confidential);\n\n        Integer ownEstimatedTime = (Integer) data.remove(\"ownEstimatedTime\");\n        if (ownEstimatedTime != null) {\n            var subscriptionService = OneDev.getInstance(SubscriptionService.class);\n            if (!subscriptionService.isSubscriptionActive())\n                throw new ExplicitException(\"An active subscription is required for this feature\");\n            if (!project.isTimeTracking())\n                throw new ExplicitException(\"Time tracking needs to be enabled for the project\");\n            if (!SecurityUtils.canScheduleIssues(subject, project))\n                throw new UnauthorizedException(\"Issue schedule permission required to set own estimated time\");\n            issue.setOwnEstimatedTime(ownEstimatedTime * 60);\n        }\n\n        List<String> iterationNames = (List<String>) data.remove(\"iterations\");\n        if (iterationNames != null) {\n            if (!SecurityUtils.canScheduleIssues(subject, project))\n                throw new UnauthorizedException(\"Issue schedule permission required to set iterations\");\n            var iterationService = OneDev.getInstance(IterationService.class);\n            for (var iterationName : iterationNames) {\n                var iteration = iterationService.findInHierarchy(project, iterationName);\n                if (iteration == null)\n                    throw new ExplicitException(\"Iteration '\" + iterationName + \"' not found\");\n                IssueSchedule schedule = new IssueSchedule();\n                schedule.setIssue(issue);\n                schedule.setIteration(iteration);\n                issue.getSchedules().add(schedule);\n            }\n        }\n\n        issue.setProject(project);\n        issue.setSubmitDate(new Date());\n        issue.setSubmitter(SecurityUtils.getUser(subject));\n        issue.setState(issueSetting.getInitialStateSpec().getName());\n\n        issue.setFieldValues(FieldUtils.getFieldValues(subject, project, data));","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/ai/IssueHelper.java#L280-L316","documentation":"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.","triggerScenarios":"createIssue called with a non-null \"iterations\" list while the subject lacks issue-schedule permission on the project.","commonSituations":"Automation running as a user without scheduling rights; AI tool calls acting on behalf of read/report-level users; recently tightened project role permissions.","solutions":["Grant 'Schedule issues' permission to the acting user's role on the project","Run the automation with an account that has schedule permission","Omit \"iterations\" (schedule them later with a permitted account)"],"exampleFix":"// before\ndata.put(\"iterations\", List.of(\"Sprint 12\"));\n// after\nif (SecurityUtils.canScheduleIssues(subject, project)) data.put(\"iterations\", List.of(\"Sprint 12\"));","handlingStrategy":"validation","validationCode":"if (data.containsKey(\"iterations\")\n        && !SecurityUtils.canScheduleIssues(subject, project))\n    throw new SecurityException(\"Actor lacks schedule-issues permission\");","typeGuard":null,"tryCatchPattern":"try {\n    issueHelper.createIssue(project, subject, data);\n} catch (UnauthorizedException e) {\n    if (e.getMessage().contains(\"iterations\")) {\n        // create issue without schedules, or rerun with a permitted account\n    }\n}","preventionTips":["Grant 'Schedule issues' permission to users/bots that assign iterations","Check canScheduleIssues before sending iteration names","Use a service account with scheduling rights for automation"],"tags":["authorization","permissions","iterations"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}