apache/druid · error · IllegalStateException

Could not find the dimension spec for ordering column

Error message

Could not find the dimension spec for ordering column %s

What it means

DefaultLimitSpec.makeComparator builds a comparator chain for the limit spec. When an ordering column is a dimension (found in dimensionsMap), it filters the dimensions list for the spec with the matching outputName; if dimensionsMap contains the name but the dimensions stream yields no spec (inconsistent map/list state), an IllegalStateException is thrown. This is an internal consistency failure between the derived map and the dimension spec list.

Solutions

  1. Ensure each ordering column appears in exactly one dimension spec with a unique outputName.
  2. Rebuild the query spec so dimensionsMap and dimensions are derived from the same list (use the provided builder helpers rather than hand-rolled maps).
  3. If this arises during normal Druid usage (not custom code), it indicates a bug — collect the query spec and file an issue.

Example fix

// before: two dimensions with same outputName "user"
// after: deduplicate
List<DimensionSpec> distinct = dims.stream().distinct().collect(Collectors.toList());
return DefaultLimitSpec.sortingComparatorWithAggregators(orderings, distinct, aggregators);
Defensive patterns

Strategy: validation

Validate before calling

long distinctNames = dimensions.stream().map(DimensionSpec::getOutputName).distinct().count();
if (distinctNames != dimensions.size()) {
  throw new IllegalArgumentException("Duplicate dimension outputName detected");
}

Prevention

When it happens

Trigger: makeComparator encounters columnName present in dimensionsMap but dimensions.stream().filter(ds -> ds.getOutputName().equals(columnName)).findFirst() is empty — e.g. duplicate dimension outputNames colliding on map keys while the filter unexpectedly fails, or API misuse producing divergent map/list inputs.

Common situations: Programmatic construction of DefaultLimitSpec.sortingComparatorWithAggregators with mismatched dimensions/aggregators collections; duplicate output names; engine-internal state divergence after query rewrite.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/groupby/orderby/DefaultLimitSpec.java:392

    for (OrderByColumnSpec columnSpec : columns) {
      String columnName = columnSpec.getDimension();
      Ordering<ResultRow> nextOrdering = null;

      final int columnIndex = rowSignature.indexOf(columnName);

      if (columnIndex >= 0) {
        if (postAggregatorsMap.containsKey(columnName)) {
          //noinspection unchecked
          nextOrdering = metricOrdering(columnIndex, postAggregatorsMap.get(columnName).getComparator());
        } else if (aggregatorsMap.containsKey(columnName)) {
          //noinspection unchecked
          nextOrdering = metricOrdering(columnIndex, aggregatorsMap.get(columnName).getComparator());
        } else if (dimensionsMap.containsKey(columnName)) {
          Optional<DimensionSpec> dimensionSpec = dimensions.stream()
                                                            .filter(ds -> ds.getOutputName().equals(columnName))
                                                            .findFirst();
          if (!dimensionSpec.isPresent()) {
            throw new ISE("Could not find the dimension spec for ordering column %s", columnName);
          }
          nextOrdering = dimensionOrdering(
              columnIndex,
              dimensionSpec.get().getOutputType(),
              columnSpec.getDimensionComparator()
          );
        }
      }

      if (nextOrdering == null) {
        throw new ISE("Unknown column in order clause[%s]", columnSpec);
      }

      if (columnSpec.getDirection() == OrderByColumnSpec.Direction.DESCENDING) {
        nextOrdering = nextOrdering.reverse();
      }

      ordering = ordering == null ? nextOrdering : ordering.compound(nextOrdering);

View on GitHub (pinned to 9b90983fd2)