{"record":{"id":"77aaa3cd44960d27","repo":"apache/druid","slug":"unrecognized-state-s-found","errorCode":null,"errorMessage":"Unrecognized state[%s] found.","messagePattern":"Unrecognized state\\[(.+?)\\] found\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/util/SqlStatementResourceHelper.java","lineNumber":142,"sourceCode":"  {\n    TaskState state = taskStatusPlus.getStatusCode();\n    if (state == null) {\n      return SqlStatementState.ACCEPTED;\n    }\n\n    switch (state) {\n      case FAILED:\n        return SqlStatementState.FAILED;\n      case RUNNING:\n        if (TaskLocation.unknown().equals(taskStatusPlus.getLocation())) {\n          return SqlStatementState.ACCEPTED;\n        } else {\n          return SqlStatementState.RUNNING;\n        }\n      case SUCCESS:\n        return SqlStatementState.SUCCESS;\n      default:\n        throw new ISE(\"Unrecognized state[%s] found.\", state);\n    }\n  }\n\n  /**\n   * Populates pages list from the {@link CounterSnapshotsTree}.\n   * <br>\n   * The number of pages changes with respect to the destination\n   * <ol>\n   *   <li>{@link DataSourceMSQDestination} a single page is returned which adds all the counters of {@link SegmentGenerationProgressCounter.Snapshot}</li>\n   *   <li>{@link TaskReportMSQDestination} a single page is returned which adds all the counters of {@link ChannelCounters}</li>\n   *   <li>{@link DurableStorageMSQDestination} a page is returned for each partition, worker which has generated output rows. The pages are populated in the following order:\n   *   <ul>\n   *     <li>For each partition from 0 to N</li>\n   *     <li>For each worker from 0 to M</li>\n   *     <li>If num rows for that partition,worker combination is 0, create a page</li>\n   *     so that we maintain the record ordering.\n   *   </ul>\n   * </ol>","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/util/SqlStatementResourceHelper.java#L124-L160","documentation":"SqlStatementState is derived from the underlying controller task's status; getSqlStatementState's switch exhaustively maps known states and throws ISE for anything unrecognized, guarding against future/unknown task states.","triggerScenarios":"The MSQ controller task reports a state not in the enum mapping (e.g. a new state added in a newer Druid version while an older broker parses it, or a corrupt/foreign status payload).","commonSituations":"Rolling upgrades with mixed broker/task-node versions; querying a task whose status JSON contains an unexpected state value.","solutions":["Upgrade all Druid nodes to a consistent version so state enums match","Check the actual task state via the tasks API and re-poll","If a transient/corrupt status, re-fetch the task status"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// only re-poll when the raw state is a known one\nSet<String> known = Set.of(\"RUNNING\",\"SUCCESS\",\"FAILED\",\"PENDING\",\"CANCELED\");\nif (!known.contains(rawState)) { scheduleRepoll(); }","typeGuard":null,"tryCatchPattern":"try {\n  state = SqlStatementResourceHelper.getSqlStatementState(status);\n} catch (ISE e) {\n  // unknown state (version skew); re-poll or upgrade cluster\n}","preventionTips":["Keep broker and overlord/task node versions aligned","Re-fetch task status on unexpected values","Handle new states gracefully after upgrades"],"tags":["msq","state-machine","version-compatibility"],"backgroundTag":"invalid-enum-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}