apache/druid · error · IllegalArgumentException (IAE)

Cannot provide 'order' incompatible with 'orderBy'

Error message

Cannot provide 'order' incompatible with 'orderBy'

What it means

verifyAndReconcileOrdering reconciles the legacy 'order' property with the newer 'orderBy' list. If the user supplied both, and the computed order derived from orderBy differs from the explicitly requested order, the query is contradictory and Druid throws IAE at query construction.

Source

Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQuery.java:545

  {
    final List<OrderBy> orderByRetVal;
    final Order orderRetVal;

    // Compute the returned orderBy.
    if (orderByFromUser != null) {
      orderByRetVal = orderByFromUser;
    } else if (orderFromUser == null || orderFromUser == Order.NONE) {
      orderByRetVal = Collections.emptyList();
    } else {
      orderByRetVal = Collections.singletonList(new OrderBy(ColumnHolder.TIME_COLUMN_NAME, orderFromUser));
    }

    // Compute the returned order.
    orderRetVal = computeTimeOrderFromOrderBys(orderByRetVal);

    // Verify compatibility, if the user specified both kinds of ordering.
    if (orderFromUser != null && orderFromUser != Order.NONE && orderRetVal != orderFromUser) {
      throw new IAE("Cannot provide 'order' incompatible with 'orderBy'");
    }

    return Pair.of(orderByRetVal, orderRetVal);
  }

  /**
   * Compute time ordering based on a list of orderBys.
   *
   * Returns {@link Order#ASCENDING} or {@link Order#DESCENDING} if the ordering is time-based; returns
   * {@link Order#NONE} otherwise. Importantly, this means that the returned order is not necessarily compatible
   * with the input orderBys.
   */
  @Nullable
  private static Order computeTimeOrderFromOrderBys(final List<OrderBy> orderBys)
  {
    if (orderBys.size() == 1) {
      final OrderBy orderByColumn = Iterables.getOnlyElement(orderBys);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Remove the legacy 'order' property and keep only 'orderBy'
  2. Align 'order' with what the orderBy list implies (ascending/descending for __time-only orderBy)
  3. Keep only 'order' and drop orderBy if simple time ordering suffices

Example fix

// before
{"queryType":"scan","columns":["__time"],"order":"descending","orderBy":[{"columnName":"country"}]}
// after
{"queryType":"scan","columns":["__time","country"],"orderBy":[{"columnName":"country"}]}
Defensive patterns

Strategy: validation

Validate before calling

if (raw.order != null && raw.order != Order.NONE && raw.orderBy != null) {
  throw new IllegalArgumentException("Provide either 'order' or 'orderBy', not both");
}

Try / catch

try {
  ScanQuery q = objectMapper.readValue(json, ScanQuery.class);
} catch (IllegalArgumentException e) {
  // strip legacy 'order' field and retry
}

Prevention

When it happens

Trigger: Constructing/deserializing a ScanQuery where 'order' is non-null, not NONE, and computeTimeOrderFromOrderBys(orderBys) yields a different Order than the user-specified orderFromUser (e.g. order:"descending" with orderBy on a non-__time column).

Common situations: Migrating queries from 'order' to 'orderBy' where both were left in the JSON; templated queries where a UI injected orderBy while the payload kept the old order field.

Related errors


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