apache/druid · error · IllegalStateException

Cannot reorder[ ] scan data right now

Error message

Cannot reorder[%s] scan data right now

What it means

LazilyDecoratedRowsAndColumns.materialize() can apply intervals, filters, limits, and virtual columns lazily, but re-ordering scan data is not implemented. If an ordering decoration is set when materialization happens, Druid throws ISE. This is a not-yet-implemented capability, not a data problem.

Solutions

  1. Remove the ordering requirement from the scan at this pipeline stage
  2. Sort explicitly after materialization instead of relying on scan ordering
  3. Use a cursor/scan path that supports ordering directly rather than the decorated wrapper
Defensive patterns

Strategy: try-catch

Validate before calling

if (decoration.getOrdering() != null) {
  throw new IllegalStateException("ordering unsupported on LazilyDecoratedRowsAndColumns; sort explicitly");
}

Try / catch

try {
  rows = lazilyDecorated.materialize();
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Cannot reorder")) {
    rows = sortExplicitly(lazilyDecorated);
  } else throw e;
}

Prevention

When it happens

Trigger: A scan-backed RowsAndColumns decorated with a non-null ordering is materialized (via thePair) before the ordering can be honored.

Common situations: Query or downstream operator requests ordered scan output through the lazily decorated wrapper; internal pipeline stages requesting ordering that only a full re-sort could satisfy.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/rowsandcols/LazilyDecoratedRowsAndColumns.java:182

    if (needsMaterialization()) {
      final Pair<byte[], RowSignature> thePair = materialize();
      if (thePair == null) {
        reset(new EmptyRowsAndColumns());
      } else {
        reset(new ColumnBasedFrameRowsAndColumns(Frame.wrap(thePair.lhs), thePair.rhs));
      }
    }
  }

  private boolean needsMaterialization()
  {
    return interval != null || filter != null || limit.isPresent() || ordering != null || virtualColumns != null;
  }

  private Pair<byte[], RowSignature> materialize()
  {
    if (ordering != null) {
      throw new ISE("Cannot reorder[%s] scan data right now", ordering);
    }

    final CursorFactory as = base.as(CursorFactory.class);
    if (as == null) {
      return naiveMaterialize(base);
    } else {
      return materializeCursorFactory(as);
    }
  }

  private void reset(RowsAndColumns rac)
  {
    base = rac;
    interval = null;
    filter = null;
    virtualColumns = null;
    limit = OffsetLimit.NONE;
    viewableColumns = null;

View on GitHub (pinned to 9b90983fd2)