SonarSource/sonarqube · error · IllegalArgumentException

Transition '%s' not supported. Only %s are supported.

Error message

Transition '%s' not supported. Only %s are supported.

What it means

Thrown by AnticipatedTransitionParser.validateAnticipatedTransitions when a workflow transition key supplied in an anticipated-transition payload is not one of the allowed CodeQualityIssueWorkflowTransition values. The parser resolves the submitted transition string via CodeQualityIssueWorkflowTransition.fromKey and rejects both unknown keys and known keys that are not in the ALLOWED_TRANSITIONS whitelist. It protects the anticipated-transitions WS endpoint from persisting unsupported workflow state changes.

Source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParser.java:53

  private static final String TRANSITION_NOT_SUPPORTED_ERROR_MESSAGE = "Transition '%s' not supported." + " Only %s are supported.".formatted(ALLOWED_TRANSITIONS.stream()
    .map(s -> "'" + s + "'").collect(Collectors.joining(",")));

  public List<AnticipatedTransition> parse(String requestBody, String userUuid, String projectKey) {
    List<GsonAnticipatedTransition> anticipatedTransitions;
    try {
      anticipatedTransitions = Arrays.asList(GSON.fromJson(requestBody, GsonAnticipatedTransition[].class));
    } catch (Exception e) {
      throw new IllegalStateException("Unable to parse anticipated transitions from request body.", e);
    }
    validateAnticipatedTransitions(anticipatedTransitions);
    return mapBodyToAnticipatedTransitions(anticipatedTransitions, userUuid, projectKey);
  }

  private static void validateAnticipatedTransitions(List<GsonAnticipatedTransition> anticipatedTransitions) {
    for (GsonAnticipatedTransition anticipatedTransition : anticipatedTransitions) {
      var transitionEnum = CodeQualityIssueWorkflowTransition.fromKey(anticipatedTransition.transition());
      if (transitionEnum.isEmpty() || !ALLOWED_TRANSITIONS.contains(transitionEnum.get())) {
        throw new IllegalArgumentException(String.format(TRANSITION_NOT_SUPPORTED_ERROR_MESSAGE, anticipatedTransition.transition()));
      }
    }
  }

  private static List<AnticipatedTransition> mapBodyToAnticipatedTransitions(List<GsonAnticipatedTransition> anticipatedTransitions, String userUuid, String projectKey) {
    return anticipatedTransitions.stream()
      .map(anticipatedTransition -> new AnticipatedTransition(
        null,
        projectKey,
        userUuid,
        RuleKey.parse(anticipatedTransition.ruleKey()),
        anticipatedTransition.message(),
        anticipatedTransition.filePath(),
        anticipatedTransition.line(),
        anticipatedTransition.lineHash(),
        anticipatedTransition.transition(),
        anticipatedTransition.comment()))
      .toList();

View on GitHub (pinned to 184c821202)

Solutions

  1. Replace the transition key with one of the transitions allowed by ALLOWED_TRANSITIONS (the second %s in the message lists them).
  2. Check the exact key casing/spelling against CodeQualityIssueWorkflowTransition keys.
  3. If the transition is not supported, remove it from the payload or perform the transition through the standard api/issues/do_transition endpoint instead.
  4. On upgrade, re-check the allowed transitions list since it may have changed between versions.

Example fix

// before
{"transition": "close_issue"}
// after
{"transition": "close"}
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = ['wontfix', 'falsepositive', 'accept']; // from ALLOWED_TRANSITIONS
payload.transitions.forEach(t => { if (!ALLOWED.includes(t.transition)) throw new Error('Unsupported transition: ' + t.transition); });

Type guard

function isAllowedTransition(t) { return typeof t.transition === 'string' && ALLOWED_TRANSITIONS.includes(t.transition); }

Prevention

When it happens

Trigger: POSTing to the anticipated transitions WS endpoint with a body whose transition field is misspelled, uses a legacy/unsupported key, or names a valid transition (e.g. 'close') that is not in ALLOWED_TRANSITIONS.

Common situations: Automation scripts bulk-transitioning issues with hand-written transition keys; clients written against an older SonarQube API whose transitions were narrowed; typos like 'wont-fix' vs 'wontfix'; copying transition names from the web UI rather than the supported enum.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/657e5876e39465d9. Report an issue: GitHub.