apache/druid · error · IllegalStateException (ISE)

Row came from an unscanned interval

Error message

Row came from an unscanned interval

What it means

While draining the priority queue in stableLimitingSort, each emitted row's timestamp must fall inside one of the intervals the query declared it was scanning. A row whose timestamp matches no interval means the interval bookkeeping desynchronized from the data, so Druid throws this IllegalStateException.

Solutions

  1. Verify the query's intervals/segment descriptors actually cover all rows' timestamps in the targeted segments.
  2. Reindex the offending segments so row timestamps match their shard intervals.
  3. Check for custom code building MultipleSpecificSegmentSpec with incorrect per-segment intervals.
  4. If caused by data/ingestion misalignment, fix the ingestion granularity and compact the affected segments.
Defensive patterns

Strategy: validation

Validate before calling

if (query.getIntervals() != null) {
  for (Interval iv : query.getQuerySegmentSpec().getIntervals(query)) {
    // confirm segment min/max time falls within iv
  }
}

Try / catch

try {
  results = runner.run(QueryPlus.wrap(query), ctx).toList();
} catch (IllegalStateException e) {
  if (e.getMessage().equals("Row came from an unscanned interval")) { /* widen intervals or reindex segments */ }
  else throw e;
}

Prevention

When it happens

Trigger: mergeRunners with time-ordering where the yielder returns a row whose event time is not contained by any interval in intervalsOrdered — e.g. intervals in the query spec do not actually cover the segment data's timestamps, or segment/intervals pairs were assembled incorrectly.

Common situations: Queries with MultipleSpecificSegmentSpec built by custom code where descriptor intervals were computed wrongly; data written outside the segment's declared interval (granularity misalignment); clock/timezone issues causing timestamps outside shard intervals.

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/446659b0fa8f420d. Report an issue: GitHub.

Appendix: source

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

      while (!doneScanning) {
        ScanResultValue next = yielder.get();
        List<ScanResultValue> singleEventScanResultValues = next.toSingleEventScanResultValues();
        for (ScanResultValue srv : singleEventScanResultValues) {
          numRowsScanned++;
          // Using an intermediate unbatched ScanResultValue is not that great memory-wise, but the column list
          // needs to be preserved for queries using the compactedList result format
          sorter.add(srv);

          // Finish scanning the interval containing the limit row
          if (numRowsScanned > limit && finalInterval == null) {
            long timestampOfLimitRow = srv.getFirstEventTimestamp(scanQuery.getResultFormat());
            for (Interval interval : intervalsOrdered) {
              if (interval.contains(timestampOfLimitRow)) {
                finalInterval = interval;
              }
            }
            if (finalInterval == null) {
              throw new ISE("Row came from an unscanned interval");
            }
          }
        }
        yielder = yielder.next(null);
        doneScanning = yielder.isDone() ||
                       (finalInterval != null &&
                        !finalInterval.contains(next.getFirstEventTimestamp(scanQuery.getResultFormat())));
      }

      final List<ScanResultValue> sortedElements = new ArrayList<>(sorter.size());
      Iterators.addAll(sortedElements, sorter.drain());
      return Sequences.simple(sortedElements);
    }
    finally {
      yielder.close();
    }
  }

View on GitHub (pinned to 9b90983fd2)