{"record":{"id":"210ca907a37364c6","repo":"apache/druid","slug":"stage-d-output-mode-not-available","errorCode":null,"errorMessage":"Stage[%d] output mode not available","messagePattern":"Stage\\[(.+?)\\] output mode not available","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/input/stage/StageInputSpecSlicer.java","lineNumber":73,"sourceCode":"  public boolean canSliceDynamic(InputSpec inputSpec)\n  {\n    return false;\n  }\n\n  @Override\n  public List<InputSlice> sliceStatic(InputSpec inputSpec, @Nullable SegmentPruner segmentPruner, int maxNumSlices)\n  {\n    final StageInputSpec stageInputSpec = (StageInputSpec) inputSpec;\n\n    final ReadablePartitions stagePartitions = stagePartitionsMap.get(stageInputSpec.getStageNumber());\n    final OutputChannelMode outputChannelMode = stageOutputChannelModeMap.get(stageInputSpec.getStageNumber());\n\n    if (stagePartitions == null) {\n      throw new ISE(\"Stage[%d] output partitions not available\", stageInputSpec.getStageNumber());\n    }\n\n    if (outputChannelMode == null) {\n      throw new ISE(\"Stage[%d] output mode not available\", stageInputSpec.getStageNumber());\n    }\n\n    // Decide how many workers to use, and assign inputs.\n    final List<ReadablePartitions> workerPartitions = stagePartitions.split(maxNumSlices);\n    final List<InputSlice> retVal = new ArrayList<>();\n\n    for (final ReadablePartitions partitions : workerPartitions) {\n      retVal.add(\n          new StageInputSlice(\n              stageInputSpec.getStageNumber(),\n              partitions,\n              outputChannelMode\n          )\n      );\n    }\n\n    return retVal;\n  }","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/input/stage/StageInputSpecSlicer.java#L55-L91","documentation":"Alongside partitions, sliceStatic also looks up each stage's output channel mode. A null entry means the slicer was not told how the upstream stage delivers output (memory vs disk), which is required to build input slices, so it throws ISE.","triggerScenarios":"sliceStatic on a StageInputSpec whose stageOutputChannelModeMap has no entry for that stage number - the stage's output mode was never registered when the query kernel was built.","commonSituations":"Same sequencing/wiring bugs as missing partitions: kernel built with an incomplete map, stage numbering mismatch, or a custom stage factory not registering channel modes.","solutions":["Ensure stageOutputChannelModeMap is populated for every stage referenced by StageInputSpec inputs.","Verify stage numbers in the DAG match those used when building the maps.","If hit on a stock query, gather controller logs and file a Druid MSQ bug - this reflects an internal initialization gap."],"exampleFix":"// before\nImmutableMap<Integer, OutputChannelMode> modes = ImmutableMap.of(1, mode1); // stage 2 missing\n// after\nImmutableMap<Integer, OutputChannelMode> modes = ImmutableMap.of(1, mode1, 2, mode2);","handlingStrategy":"validation","validationCode":"if (!stageOutputChannelModeMap.containsKey(stageNumber)) {\n  throw new IllegalStateException(\"No output channel mode registered for stage \" + stageNumber);\n}\nslicer.sliceStatic(inputSpec, maxSlices);","typeGuard":null,"tryCatchPattern":"try {\n  slicer.sliceStatic(inputSpec, maxSlices);\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"output mode not available\")) {\n    log.error(e, \"Channel mode missing for stage; check kernel construction\");\n  } else {\n    throw e;\n  }\n}","preventionTips":["Register output channel modes for every stage when building the query kernel.","Assert parity between stagePartitionsMap and stageOutputChannelModeMap keys.","Cover multi-stage DAGs with kernel construction unit tests."],"tags":["msq","stage-dependency","missing-state","channel-mode"],"backgroundTag":"resource-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}