{"record":{"id":"657e5876e39465d9","repo":"SonarSource/sonarqube","slug":"transition-s-not-supported-only-s-are-support","errorCode":null,"errorMessage":"Transition '%s' not supported. Only %s are supported.","messagePattern":"Transition '(.+?)' not supported\\. Only (.+?) are supported\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParser.java","lineNumber":53,"sourceCode":"  private static final String TRANSITION_NOT_SUPPORTED_ERROR_MESSAGE = \"Transition '%s' not supported.\" + \" Only %s are supported.\".formatted(ALLOWED_TRANSITIONS.stream()\n    .map(s -> \"'\" + s + \"'\").collect(Collectors.joining(\",\")));\n\n  public List<AnticipatedTransition> parse(String requestBody, String userUuid, String projectKey) {\n    List<GsonAnticipatedTransition> anticipatedTransitions;\n    try {\n      anticipatedTransitions = Arrays.asList(GSON.fromJson(requestBody, GsonAnticipatedTransition[].class));\n    } catch (Exception e) {\n      throw new IllegalStateException(\"Unable to parse anticipated transitions from request body.\", e);\n    }\n    validateAnticipatedTransitions(anticipatedTransitions);\n    return mapBodyToAnticipatedTransitions(anticipatedTransitions, userUuid, projectKey);\n  }\n\n  private static void validateAnticipatedTransitions(List<GsonAnticipatedTransition> anticipatedTransitions) {\n    for (GsonAnticipatedTransition anticipatedTransition : anticipatedTransitions) {\n      var transitionEnum = CodeQualityIssueWorkflowTransition.fromKey(anticipatedTransition.transition());\n      if (transitionEnum.isEmpty() || !ALLOWED_TRANSITIONS.contains(transitionEnum.get())) {\n        throw new IllegalArgumentException(String.format(TRANSITION_NOT_SUPPORTED_ERROR_MESSAGE, anticipatedTransition.transition()));\n      }\n    }\n  }\n\n  private static List<AnticipatedTransition> mapBodyToAnticipatedTransitions(List<GsonAnticipatedTransition> anticipatedTransitions, String userUuid, String projectKey) {\n    return anticipatedTransitions.stream()\n      .map(anticipatedTransition -> new AnticipatedTransition(\n        null,\n        projectKey,\n        userUuid,\n        RuleKey.parse(anticipatedTransition.ruleKey()),\n        anticipatedTransition.message(),\n        anticipatedTransition.filePath(),\n        anticipatedTransition.line(),\n        anticipatedTransition.lineHash(),\n        anticipatedTransition.transition(),\n        anticipatedTransition.comment()))\n      .toList();","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/anticipatedtransition/AnticipatedTransitionParser.java#L35-L71","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Replace the transition key with one of the transitions allowed by ALLOWED_TRANSITIONS (the second %s in the message lists them).","Check the exact key casing/spelling against CodeQualityIssueWorkflowTransition keys.","If the transition is not supported, remove it from the payload or perform the transition through the standard api/issues/do_transition endpoint instead.","On upgrade, re-check the allowed transitions list since it may have changed between versions."],"exampleFix":"// before\n{\"transition\": \"close_issue\"}\n// after\n{\"transition\": \"close\"}","handlingStrategy":"validation","validationCode":"const ALLOWED = ['wontfix', 'falsepositive', 'accept']; // from ALLOWED_TRANSITIONS\npayload.transitions.forEach(t => { if (!ALLOWED.includes(t.transition)) throw new Error('Unsupported transition: ' + t.transition); });","typeGuard":"function isAllowedTransition(t) { return typeof t.transition === 'string' && ALLOWED_TRANSITIONS.includes(t.transition); }","tryCatchPattern":null,"preventionTips":["Keep the allowed transition list in sync with the server version you target.","Copy transition keys from the API docs/enums, not the UI labels."],"tags":["webapi","validation","transitions","sonarqube"],"backgroundTag":"invalid-enum-value","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}