{"record":{"id":"3424228d5ba80112","repo":"theonedev/onedev","slug":"state-is-required","errorCode":null,"errorMessage":"State is required","messagePattern":"State is required","errorType":"http","errorClass":"NotAcceptableException","httpStatus":406,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/ai/TodResource.java","lineNumber":674,"sourceCode":"\n    @Path(\"/change-issue-state\")\n    @POST\n    public Map<String, Object> changeIssueState(\n                @QueryParam(\"currentProject\") @NotNull String currentProjectPath, \n                @QueryParam(\"reference\") @NotNull String issueReference, \n                @NotNull Map<String, Serializable> data) {\n        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(","sourceCodeStart":656,"sourceCodeEnd":692,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/ai/TodResource.java#L656-L692","documentation":"Guard in the change-issue-state endpoint of TodResource: the submitted state-change data contained no state field, so there is no target state to move the issue to. The caller (an AI agent) must supply the desired state name.","triggerScenarios":"Calling the AI tod state-change endpoint with a data map lacking the 'state' key, or with state normalized to null (e.g., empty value removed by IssueHelper.normalizeData).","commonSituations":"Client sends only a comment or field values expecting the transition to be inferred; typo in key name ('Status' instead of 'state'); payload built programmatically without the state entry.","solutions":["Include a non-empty 'state' key in the request data matching a state defined in the project's issue workflow.","Fix the key spelling to lowercase 'state'.","Validate the payload before sending."],"exampleFix":"// before\nMap<String, Serializable> data = Map.of(\"comment\", \"done\");\n// after\nMap<String, Serializable> data = Map.of(\"state\", \"Done\", \"comment\", \"done\");","handlingStrategy":"validation","validationCode":"if (!data || typeof data.state !== \"string\" || data.state.trim() === \"\") {\n  throw new Error(\"'state' is required to transition an issue\");\n}","typeGuard":"function hasState(d) {\n  return typeof d === \"object\" && d !== null && typeof d.state === \"string\" && d.state.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Always include 'state' in transition payloads.","Normalize key casing before sending (lowercase 'state').","Validate payloads against the endpoint's expected schema in tests."],"tags":["validation","missing-field","issue-workflow","onedev"],"backgroundTag":"missing-required-argument","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"}