apache/druid · error · UnsupportedOperationException (UOE)

Limit of %,d rows not supported for priority queue strategy…

Error message

Limit of %,d rows not supported for priority queue strategy of time-ordering scan results

What it means

When a scan query uses resultOrdering (time-ordering), rows are buffered in an in-memory priority queue, so the scanRows limit must fit an int. A limit above Integer.MAX_VALUE cannot be allocated and is rejected with this UOE.

Solutions

  1. Lower the scan query limit (scanRows / SQL LIMIT) to at most Integer.MAX_VALUE, ideally a realistic page size.
  2. If you truly need unbounded results, remove the time-ordering ('descending' ordering) so the priority-queue strategy is not used and pagination via scanRowsOffset applies.
  3. For large exports, iterate with ordered batches (limit + offset) instead of one giant ordered scan.

Example fix

// before
ScanQuery q = new ScanQueryBuilder().order(Order.DESCENDING).limit(Long.MAX_VALUE).build();
// after
ScanQuery q = new ScanQueryBuilder().order(Order.DESCENDING).limit(1_000_000).build();
Defensive patterns

Strategy: validation

Validate before calling

if (query.getOrdering() != null && query.getScanRowsLimit() > Integer.MAX_VALUE) {
  throw new IllegalArgumentException("scanRows limit too large for time-ordered scan");
}

Type guard

boolean limitFitsPriorityQueue(ScanQuery q) { return q.getScanRowsLimit() <= Integer.MAX_VALUE; }

Try / catch

try {
  results = runner.run(QueryPlus.wrap(query), ctx).toList();
} catch (UnsupportedOperationException e) {
  if (e.getMessage().contains("not supported for priority queue")) { query = query.withLimit(Integer.MAX_VALUE); }
  else throw e;
}

Prevention

When it happens

Trigger: Running a ScanQuery with getOrdering() set (descending time-ordering) and scanRowsLimit > 2147483647 (e.g. Long.MAX_VALUE, often from a default/unbounded limit configured for a non-time-ordered scan).

Common situations: Setting scanRowsLimit to Long.MAX_VALUE or a huge default in client code/SQL (LIMIT-less scan defaults) while also enabling ordering: 'descending' in SQL scan queries.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQueryRunnerFactory.java:222

      }
    };
  }

  /**
   * Returns a sorted and limited copy of the provided {@param inputSequence}. Materializes the full sequence
   * in memory before returning it. The amount of memory use is limited by the limit of the {@param scanQuery}.
   */
  @VisibleForTesting
  Sequence<ScanResultValue> stableLimitingSort(
      Sequence<ScanResultValue> inputSequence,
      ScanQuery scanQuery,
      List<Interval> intervalsOrdered
  ) throws IOException
  {
    Comparator<ScanResultValue> comparator = scanQuery.getResultOrdering();

    if (scanQuery.getScanRowsLimit() > Integer.MAX_VALUE) {
      throw new UOE(
          "Limit of %,d rows not supported for priority queue strategy of time-ordering scan results",
          scanQuery.getScanRowsLimit()
      );
    }

    // Converting the limit from long to int could theoretically throw an ArithmeticException but this branch
    // only runs if limit < MAX_LIMIT_FOR_IN_MEMORY_TIME_ORDERING (which should be < Integer.MAX_VALUE)
    int limit = Math.toIntExact(scanQuery.getScanRowsLimit());

    final StableLimitingSorter<ScanResultValue> sorter = new StableLimitingSorter<>(comparator, limit);

    Yielder<ScanResultValue> yielder = Yielders.each(inputSequence);

    try {
      boolean doneScanning = yielder.isDone();
      // We need to scan limit elements and anything else in the last segment
      int numRowsScanned = 0;
      Interval finalInterval = null;

View on GitHub (pinned to 9b90983fd2)