apache/druid · error · IllegalStateException

Cannot handle inputSpec of class [%s]

Error message

Cannot handle inputSpec of class [%s]

What it means

MSQ's input-slicing framework dispatches each InputSpec type to a registered InputSpecSlicer via getSlicer. This ISE is thrown when an InputSpec class has no slicer registered in splitterMap, meaning the query contains an input spec type the current slicer does not know how to split across workers.

Source

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

  @Override
  public List<InputSlice> sliceDynamic(
      InputSpec inputSpec,
      @Nullable SegmentPruner segmentPruner,
      int maxNumSlices,
      int maxFilesPerSlice,
      long maxBytesPerSlice
  )
  {
    return getSlicer(inputSpec.getClass()).sliceDynamic(inputSpec, segmentPruner, maxNumSlices, maxFilesPerSlice, maxBytesPerSlice);
  }

  private InputSpecSlicer getSlicer(final Class<? extends InputSpec> clazz)
  {
    final InputSpecSlicer slicer = splitterMap.get(clazz);

    if (slicer == null) {
      throw new ISE("Cannot handle inputSpec of class [%s]", clazz.getName());
    }

    return slicer;
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Check the InputSpec class named in the message and confirm the Druid MSQ code path that produced it is supported for this query type.
  2. If you added a custom InputSpec, register a corresponding InputSpecSlicer in the MapInputSpecSlicer's splitterMap.
  3. Verify all Druid nodes (overlord, controller, worker) run the same version so InputSpec classes match.
  4. If triggered by an unsupported datasource (e.g. lookup or inline passed where only table/stage are supported), rewrite the query to use a supported input source.

Example fix

// before
final MapInputSpecSlicer slicer = new MapInputSpecSlicer(
    ImmutableMap.of(TableInputSpec.class, tableSlicer));
slicer.sliceStatic(inputSpec, ...); // ISE for StageInputSpec
// after
final MapInputSpecSlicer slicer = new MapInputSpecSlicer(
    ImmutableMap.of(
        TableInputSpec.class, tableSlicer,
        StageInputSpec.class, stageSlicer));
Defensive patterns

Strategy: try-catch

Validate before calling

if (!ImmutableSet.of(TableInputSpec.class, StageInputSpec.class).contains(inputSpec.getClass())) {
  throw new UnsupportedOperationException("No slicer for " + inputSpec.getClass());
}

Try / catch

try {
  slicer.sliceStatic(inputSpec, maxSlices);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Cannot handle inputSpec of class")) {
    log.error(e, "Unsupported input spec %s", inputSpec.getClass().getName());
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling canSliceDynamic, sliceStatic, or sliceDynamic on a MapInputSpecSlicer whose splitterMap lacks an entry for the InputSpec subclass being sliced (e.g. a new InputSpec type added without updating the map, or an exotic data source deserialized from JSON).

Common situations: A custom extension registers a new InputSpec; a Druid version mismatch where one broker/overlord serializes a newer InputSpec that an older controller's MapInputSpecSlicer doesn't handle; wiring bugs where a slicer is constructed with a partial map of splitters.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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