theonedev/onedev · error · NotAcceptableException

No applicable manual transition spec found for current user

Error message

No applicable manual transition spec found for current user (issue: {0}, from state: {1}, to state: {2})

What it means

State transitions via the REST API must match a manual transition spec defined in the project's issue workflow that applies to the current user, current state, and target state. issue.getProject().getManualSpec(subject, issue, toState) returning null yields NotAcceptableException (HTTP 406) with issue, from-state and to-state details.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/IssueResource.java:474

		var example = new LinkedHashMap<String, Serializable>();
		example.put("field1", "value1");
		example.put("field2", new String[]{"value1", "value2"});
		return example;
	}

	@Api(order=1500)
	@Path("/{issueId}/state-transitions")
    @POST
    public Response transitState(@PathParam("issueId") Long issueId, @NotNull @Valid StateTransitionData data) {
		Issue issue = issueService.load(issueId);
		var subject = SecurityUtils.getSubject();
		var user = SecurityUtils.getUser(subject);
		ManualSpec transition = issue.getProject().getManualSpec(subject, issue, data.getState());
		if (transition == null) {
			var message = MessageFormat.format(
				"No applicable manual transition spec found for current user (issue: {0}, from state: {1}, to state: {2})",
				issue.getReference().toString(), issue.getState(), data.getState());
			throw new NotAcceptableException(message);
		}
    	
		var fieldValues = FieldUtils.getFieldValues(subject, issue.getProject(), data.getFields());
		issueChangeService.changeState(user, issue, data.getState(), fieldValues, 
				transition.getPromptFields(), transition.getRemoveFields(), data.getComment());
		return Response.ok().build();
    }

	@Api(order=1550, example = "/~downloads/projects/1/attachments/6a5a1a20-c8c0-44a5-a1bb-8a3d2a830094/attachment.txt", 
			description = "Upload attachment to issue and get attachment url via response. This url can then be used in issue description or comment")
	@Path("/{issueId}/attachments/{preferredAttachmentName}")
    @POST
	@Consumes(MediaType.APPLICATION_OCTET_STREAM)
    public String uploadAttachment(@PathParam("issueId") Long issueId, @PathParam("preferredAttachmentName") String preferredAttachmentName, InputStream input) {
		Issue issue = issueService.load(issueId);
    	if (!SecurityUtils.canModifyIssue(issue))
			throw new UnauthorizedException();
			

View on GitHub (pinned to d44925c47c)

Solutions

  1. Add/adjust a manual transition spec in Project -> Issue Setting -> Workflow for the from-state to the target state applicable to the user.
  2. Transition through intermediate states that have defined specs, in order.
  3. Verify the exact target state name matches the workflow state.
  4. Ensure the API user satisfies the transition spec's authorization/condition.

Example fix

// before
POST /api/issues/12/transit {"state":"Closed"}  // no spec Open->Closed
// after: define a manual transition Open -> Closed in the workflow, or
POST /api/issues/12/transit {"state":"In Progress"}  // then Closed
Defensive patterns

Strategy: validation

Validate before calling

const workflow = await getIssueWorkflow(projectPath);
const spec = workflow.states[state]
  ?.transitions?.find(t => t.toState === targetState && t.type === 'MANUAL' && appliesToUser(t, me));
if (!spec) throw new Error(`No manual transition ${state} -> ${targetState} for current user; check workflow`);

Try / catch

try {
  await api.transitIssueState(issueId, payload);
} catch (e) {
  if (e.status === 406 && /No applicable manual transition spec/.test(e.message))
    log.error(`Workflow has no manual transition to ${payload.state}; adjust workflow or path`);
  else throw e;
}

Prevention

When it happens

Trigger: POST to /api/issues/{issueId}/transit (transitState) with data.getState() equal to a state for which no applicable manual transition spec exists for the user — e.g., target state only reachable via other transitions, spec restricted by role/condition, or state name mismatch.

Common situations: Automations skipping multi-step workflows (attempting direct jump to a closed state); workflow customized so transitions require authorization the API user lacks; renamed states causing exact-name mismatches.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/6ddb42d108188238. Report an issue: GitHub.