apache/druid · error · IllegalStateException

Stage[%d] output mode not available

Error message

Stage[%d] output mode not available

What it means

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.

Source

Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/input/stage/StageInputSpecSlicer.java:73

  public boolean canSliceDynamic(InputSpec inputSpec)
  {
    return false;
  }

  @Override
  public List<InputSlice> sliceStatic(InputSpec inputSpec, @Nullable SegmentPruner segmentPruner, int maxNumSlices)
  {
    final StageInputSpec stageInputSpec = (StageInputSpec) inputSpec;

    final ReadablePartitions stagePartitions = stagePartitionsMap.get(stageInputSpec.getStageNumber());
    final OutputChannelMode outputChannelMode = stageOutputChannelModeMap.get(stageInputSpec.getStageNumber());

    if (stagePartitions == null) {
      throw new ISE("Stage[%d] output partitions not available", stageInputSpec.getStageNumber());
    }

    if (outputChannelMode == null) {
      throw new ISE("Stage[%d] output mode not available", stageInputSpec.getStageNumber());
    }

    // Decide how many workers to use, and assign inputs.
    final List<ReadablePartitions> workerPartitions = stagePartitions.split(maxNumSlices);
    final List<InputSlice> retVal = new ArrayList<>();

    for (final ReadablePartitions partitions : workerPartitions) {
      retVal.add(
          new StageInputSlice(
              stageInputSpec.getStageNumber(),
              partitions,
              outputChannelMode
          )
      );
    }

    return retVal;
  }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure stageOutputChannelModeMap is populated for every stage referenced by StageInputSpec inputs.
  2. Verify stage numbers in the DAG match those used when building the maps.
  3. If hit on a stock query, gather controller logs and file a Druid MSQ bug - this reflects an internal initialization gap.

Example fix

// before
ImmutableMap<Integer, OutputChannelMode> modes = ImmutableMap.of(1, mode1); // stage 2 missing
// after
ImmutableMap<Integer, OutputChannelMode> modes = ImmutableMap.of(1, mode1, 2, mode2);
Defensive patterns

Strategy: validation

Validate before calling

if (!stageOutputChannelModeMap.containsKey(stageNumber)) {
  throw new IllegalStateException("No output channel mode registered for stage " + stageNumber);
}
slicer.sliceStatic(inputSpec, maxSlices);

Try / catch

try {
  slicer.sliceStatic(inputSpec, maxSlices);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().contains("output mode not available")) {
    log.error(e, "Channel mode missing for stage; check kernel construction");
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/210ca907a37364c6. Report an issue: GitHub.