{"record":{"id":"871fe1ba605bdd94","repo":"theonedev/onedev","slug":"no-applicable-manual-transition-spec-found-for-cur","errorCode":null,"errorMessage":"No applicable manual transition spec found for current user (issue: ${issue.getReference().toString()}, from state: ${issue.getState()}, to state: ${state})","messagePattern":"No applicable manual transition spec found for current user \\(issue: (.+?), from state: (.+?), to state: (.+?)\\)","errorType":"http","errorClass":"NotAcceptableException","httpStatus":406,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/ai/TodResource.java","lineNumber":681,"sourceCode":"        var subject = SecurityUtils.getSubject();\n        var user = SecurityUtils.getUser(subject);\n        if (user == null)\n            throw new UnauthenticatedException();\n\n        var currentProject = getProject(currentProjectPath);\n\n        var issue = getIssue(currentProject, issueReference);\n        IssueHelper.normalizeData(data);\n        var state = (String) data.remove(\"state\");\n        if (state == null)\n            throw new NotAcceptableException(\"State is required\");\n        var comment = (String) data.remove(\"comment\");\n        ManualSpec transition = issue.getProject().getManualSpec(subject, issue, state);\n        if (transition == null) {\n            var message = MessageFormat.format(\n                \"No applicable manual transition spec found for current user (issue: {0}, from state: {1}, to state: {2})\",\n                issue.getReference().toString(), issue.getState(), state);\n            throw new NotAcceptableException(message);\n        }\n\n        var fieldValues = FieldUtils.getFieldValues(subject, issue.getProject(), data);\n        issueChangeService.changeState(user, issue, state, fieldValues, transition.getPromptFields(),\n                transition.getRemoveFields(), comment);\n        return IssueHelper.getDetail(currentProject, issue);\n    }\n\n    @Path(\"/ensure-issue-branch\") \n    @POST\n    public String ensureIssueBranch(\n                @QueryParam(\"currentProject\") @NotNull String currentProjectPath, \n                @QueryParam(\"reference\") @NotNull String issueReference) {\n        var subject = SecurityUtils.getSubject();\n\n        var currentProject = getProject(currentProjectPath);\n        var issue = getIssue(currentProject, issueReference);\n","sourceCodeStart":663,"sourceCodeEnd":699,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/ai/TodResource.java#L663-L699","documentation":"Thrown as NotAcceptableException when getManualSpec returns null: there is no manual transition spec in the project's issue workflow that permits this user to move the issue from its current state to the requested state. The message includes the issue reference, current state, and requested state.","triggerScenarios":"Requesting a state the workflow has no manual transition to; the transition exists but its authorization (required permission/role/group) excludes the current user; transition only defined from a different source state.","commonSituations":"Requesting a state name that exists on the board but has no incoming manual transition; user lacks the role required by the transition's authorization; workflow config changed so the old path no longer applies.","solutions":["Define or enable a manual transition spec from the issue's current state to the requested state in the project's issue workflow settings.","Grant the user the permission/role required by the existing transition spec.","Choose a different target state that has an applicable manual transition for this user."],"exampleFix":"// before\ntransition request to state \"Released\" // no manual transition defined from \"In Progress\"\n// after: add a manual transition spec In Progress -> Released (with proper authorization),\n// or request an existing applicable state like \"Done\"","handlingStrategy":"validation","validationCode":"// pre-check that a manual transition exists for this user and target state\nconst spec = project.manualSpecs.find(s =>\n  s.fromState === issue.state && s.toState === state && userMeetsAuth(s.authorization));\nif (!spec) throw new Error(`No manual transition ${issue.state} -> ${state} for this user`);","typeGuard":"function canTransition(project, issue, user, toState) {\n  return project.manualSpecs.some(s => s.fromState === issue.state && s.toState === toState\n    && s.authorizedGroups.some(g => user.groups.includes(g)));\n}","tryCatchPattern":"try {\n  await transitionIssue(...);\n} catch (e) {\n  if (e.status === 406 || /No applicable manual transition spec/.test(e.message)) {\n    // list applicable transitions for the user and pick one\n  } else throw e;\n}","preventionTips":["Query available manual transitions for the user before choosing a target state.","Keep workflow transition authorization in sync with the roles of AI agent identities.","Update automation when workflow states/transition specs change."],"tags":["issue-workflow","state-transition","authorization","onedev"],"backgroundTag":"invalid-state-transition","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}