{"record":{"id":"b878bf77eacd92a7","repo":"apache/druid","slug":"time-ordering-on-scan-queries-is-only-supported-fo","errorCode":null,"errorMessage":"Time-ordering on scan queries is only supported for queries with segment specs of type MultipleSpecificSegmentSpec or SpecificSegmentSpec...a [%s] was received instead.","messagePattern":"Time-ordering on scan queries is only supported for queries with segment specs of type MultipleSpecificSegmentSpec or SpecificSegmentSpec\\.\\.\\.a \\[(.+?)\\] was received instead\\.","errorType":"exception","errorClass":"UnsupportedOperationException (UOE)","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/scan/ScanQueryRunnerFactory.java","lineNumber":296,"sourceCode":"  @VisibleForTesting\n  List<Interval> getIntervalsFromSpecificQuerySpec(QuerySegmentSpec spec)\n  {\n    // Query segment spec must be an instance of MultipleSpecificSegmentSpec or SpecificSegmentSpec because\n    // segment descriptors need to be present for a 1:1 matching of intervals with query runners.\n    // The other types of segment spec condense the intervals (i.e. merge neighbouring intervals), eliminating\n    // the 1:1 relationship between intervals and query runners.\n    List<Interval> descriptorsOrdered;\n\n    if (spec instanceof MultipleSpecificSegmentSpec) {\n      // Ascending time order for both descriptors and query runners by default\n      descriptorsOrdered = ((MultipleSpecificSegmentSpec) spec).getDescriptors()\n                                                               .stream()\n                                                               .map(SegmentDescriptor::getInterval)\n                                                               .collect(Collectors.toList());\n    } else if (spec instanceof SpecificSegmentSpec) {\n      descriptorsOrdered = Collections.singletonList(((SpecificSegmentSpec) spec).getDescriptor().getInterval());\n    } else {\n      throw new UOE(\n          \"Time-ordering on scan queries is only supported for queries with segment specs \"\n          + \"of type MultipleSpecificSegmentSpec or SpecificSegmentSpec...a [%s] was received instead.\",\n          spec.getClass().getSimpleName()\n      );\n    }\n    return descriptorsOrdered;\n  }\n\n  @VisibleForTesting\n  Sequence<ScanResultValue> nWayMergeAndLimit(\n      List<List<QueryRunner<ScanResultValue>>> groupedRunners,\n      QueryPlus<ScanResultValue> queryPlus,\n      ResponseContext responseContext\n  )\n  {\n    // Starting from the innermost Sequences.map:\n    // (1) Deaggregate each ScanResultValue returned by the query runners\n    // (2) Combine the deaggregated ScanResultValues into a single sequence","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/scan/ScanQueryRunnerFactory.java#L278-L314","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnew ScanQuery(DataSegmentDescriptor.of(segment), ..., Order.DESCENDING); // with AllSegmentsQuerySpec\n// after: use a specific-segment spec\ndescriptors.forEach(d -> query.withQuerySegmentSpec(new MultipleSpecificSegmentSpec(descriptors)));","handlingStrategy":"validation","validationCode":"if (query.getOrdering() != null\n    && !(query.getQuerySegmentSpec() instanceof MultipleSpecificSegmentSpec)\n    && !(query.getQuerySegmentSpec() instanceof SpecificSegmentSpec)) {\n  throw new IllegalArgumentException(\"time-ordering requires specific segment specs\");\n}","typeGuard":"boolean specSupportsOrdering(QuerySegmentSpec spec) {\n  return spec instanceof MultipleSpecificSegmentSpec || spec instanceof SpecificSegmentSpec;\n}","tryCatchPattern":"try {\n  results = runner.run(QueryPlus.wrap(query), ctx).toList();\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"Time-ordering on scan queries\")) { /* drop ordering or switch spec */ }\n  else throw e;\n}","preventionTips":["Set ordering only with specific-segment specs.","Drop ORDER BY/Order.DESCENDING when using interval-based specs.","Verify specs survive broker routing unchanged."],"tags":["druid","scan-query","unsupported-operation"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}