apache/druid · error · UnsupportedOperationException (UOE)
Time-ordering on scan queries is only supported for queries…
Error message
Time-ordering on scan queries is only supported for queries with segment specs of type MultipleSpecificSegmentSpec or SpecificSegmentSpec...a [%s] was received instead.
What it means
Time-ordered scans need an explicit per-segment interval ordering, which only MultipleSpecificSegmentSpec and SpecificSegmentSpec provide. Any other query spec (e.g. AllSegmentsQuerySpec or MultipleIntervalSegmentSpec) cannot be ordered deterministically and is rejected with this UOE.
Solutions
- Remove the time-ordering (order=null / drop ORDER BY on the scan) if per-segment specs cannot be used.
- Target specific segments via SpecificSegmentSpec or MultipleSpecificSegmentSpec when ordering is required.
- Ensure broker/server versions are consistent so specific-segment specs survive query routing.
Example fix
// before new ScanQuery(DataSegmentDescriptor.of(segment), ..., Order.DESCENDING); // with AllSegmentsQuerySpec // after: use a specific-segment spec descriptors.forEach(d -> query.withQuerySegmentSpec(new MultipleSpecificSegmentSpec(descriptors)));
Defensive patterns
Strategy: validation
Validate before calling
if (query.getOrdering() != null
&& !(query.getQuerySegmentSpec() instanceof MultipleSpecificSegmentSpec)
&& !(query.getQuerySegmentSpec() instanceof SpecificSegmentSpec)) {
throw new IllegalArgumentException("time-ordering requires specific segment specs");
} Type guard
boolean specSupportsOrdering(QuerySegmentSpec spec) {
return spec instanceof MultipleSpecificSegmentSpec || spec instanceof SpecificSegmentSpec;
} Try / catch
try {
results = runner.run(QueryPlus.wrap(query), ctx).toList();
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("Time-ordering on scan queries")) { /* drop ordering or switch spec */ }
else throw e;
} Prevention
- Set ordering only with specific-segment specs.
- Drop ORDER BY/Order.DESCENDING when using interval-based specs.
- Verify specs survive broker routing unchanged.
When it happens
Trigger: Running a ScanQuery with resultOrdering set while its query spec is MultipleIntervalSegmentSpec or AllSegmentsQuerySpec — typically when a client sets order=descending on a query that also uses broad interval-based segment selection.
Common situations: SQL scan queries with ORDER BY __time DESC planned against interval specs; custom tools constructing ScanQuery with default specs plus ordering; older clients whose broker collapsed specific specs into interval specs.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unable to get first event timestamp using result format of
- Unsupported resultFormat for array-based results
- Aggregator[ ] cannot vectorize
- AppenderatorsManager methods should only called by services…
- ApproximateHistogramBufferAggregator does not support…
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/b878bf77eacd92a7.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQueryRunnerFactory.java:296
@VisibleForTesting
List<Interval> getIntervalsFromSpecificQuerySpec(QuerySegmentSpec spec)
{
// Query segment spec must be an instance of MultipleSpecificSegmentSpec or SpecificSegmentSpec because
// segment descriptors need to be present for a 1:1 matching of intervals with query runners.
// The other types of segment spec condense the intervals (i.e. merge neighbouring intervals), eliminating
// the 1:1 relationship between intervals and query runners.
List<Interval> descriptorsOrdered;
if (spec instanceof MultipleSpecificSegmentSpec) {
// Ascending time order for both descriptors and query runners by default
descriptorsOrdered = ((MultipleSpecificSegmentSpec) spec).getDescriptors()
.stream()
.map(SegmentDescriptor::getInterval)
.collect(Collectors.toList());
} else if (spec instanceof SpecificSegmentSpec) {
descriptorsOrdered = Collections.singletonList(((SpecificSegmentSpec) spec).getDescriptor().getInterval());
} else {
throw new UOE(
"Time-ordering on scan queries is only supported for queries with segment specs "
+ "of type MultipleSpecificSegmentSpec or SpecificSegmentSpec...a [%s] was received instead.",
spec.getClass().getSimpleName()
);
}
return descriptorsOrdered;
}
@VisibleForTesting
Sequence<ScanResultValue> nWayMergeAndLimit(
List<List<QueryRunner<ScanResultValue>>> groupedRunners,
QueryPlus<ScanResultValue> queryPlus,
ResponseContext responseContext
)
{
// Starting from the innermost Sequences.map:
// (1) Deaggregate each ScanResultValue returned by the query runners
// (2) Combine the deaggregated ScanResultValues into a single sequenceView on GitHub (pinned to 9b90983fd2)