{"record":{"id":"54f91cc83284f40e","repo":"apache/druid","slug":"no-such-stage-s-54f91c","errorCode":null,"errorMessage":"No such stage[%s]","messagePattern":"No such stage\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/kernel/controller/ControllerQueryKernel.java","lineNumber":467,"sourceCode":"   * Returns the definition of a given stage.\n   *\n   * @throws NullPointerException if there is no stage with the given ID\n   */\n  public StageDefinition getStageDefinition(final StageId stageId)\n  {\n    return queryDef.getStageDefinition(stageId);\n  }\n\n  /**\n   * Returns the {@link OutputChannelMode} for a given stage.\n   *\n   * @throws IllegalStateException if there is no stage with the given ID\n   */\n  public OutputChannelMode getStageOutputChannelMode(final StageId stageId)\n  {\n    final OutputChannelMode outputChannelMode = stageOutputChannelModes.get(stageId);\n    if (outputChannelMode == null) {\n      throw new ISE(\"No such stage[%s]\", stageId);\n    }\n\n    return outputChannelMode;\n  }\n\n  /**\n   * Whether query results are readable.\n   */\n  public boolean canReadQueryResults()\n  {\n    final StageId finalStageId = queryDef.getFinalStageDefinition().getId();\n    final ControllerStageTracker stageTracker = stageTrackers.get(finalStageId);\n    if (stageTracker == null) {\n      return false;\n    } else {\n      final OutputChannelMode outputChannelMode = stageOutputChannelModes.get(finalStageId);\n      if (outputChannelMode == OutputChannelMode.MEMORY) {\n        return stageTracker.getPhase().isRunning();","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/kernel/controller/ControllerQueryKernel.java#L449-L485","documentation":"getStageOutputChannelMode looks up the stage's OutputChannelMode in the kernel's map and throws IllegalStateException 'No such stage[%s]' when the StageId is absent. The kernel only registers stages it has created, so querying a mode for an unknown or not-yet-created stage is an internal invariant violation.","triggerScenarios":"Calling getStageOutputChannelMode with a StageId that was never added to the kernel, one already removed/cleaned up, or an id for a different query; ordering bugs where the method is called before the kernel stage is initialized.","commonSituations":"Custom controller code querying a stage after the query failed or was canceled and the kernel was torn down; mixing up StageIds across queries; race between stage creation and consumers requesting the channel mode.","solutions":["Verify the StageId belongs to the same query and its stage number is within the created range (getStageCount/getStage)","Check the query/controller lifecycle — the stage may have been cleaned up after completion or failure","Add the stage via createNewKernel before reading its channel mode, or guard the lookup with stageOutputChannelModes.containsKey"],"exampleFix":"// before\nOutputChannelMode mode = kernel.getStageOutputChannelMode(stageId);\n// after\nif (!kernel.doesStageExist(stageId)) { throw new IllegalStateException(\"Stage not created: \" + stageId); }\nOutputChannelMode mode = kernel.getStageOutputChannelMode(stageId);","handlingStrategy":"try-catch","validationCode":"if (!kernel.doesStageExist(stageId) || !stageId.getQueryId().equals(queryDef.getQueryId())) { throw new IllegalStateException(\"Stage not available: \" + stageId); }","typeGuard":"boolean stageExists(ControllerQueryKernel k, StageId id) { return k.getStages().stream().anyMatch(s -> s.getId().equals(id)); }","tryCatchPattern":"try { mode = kernel.getStageOutputChannelMode(stageId); } catch (IllegalStateException e) { log.warn(\"Stage {} not in kernel (query done or wrong id)\", stageId); mode = OutputChannelMode.NONE; }","preventionTips":["Only query stages created in the same kernel/query lifetime","Check query state (RUNNING vs finished/canceled) before touching stage metadata","Log and compare StageId queryIds on mismatch","Avoid caching StageIds across controller restarts"],"tags":["java","illegal-state","msq"],"backgroundTag":"internal-invariant-violation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}