apache/druid · error · IllegalArgumentException
The __time column must be selected if the results are time-o
Error message
The __time column must be selected if the results are time-ordered.
What it means
When a ScanQuery has a time-ordering ('order':'ascending'/'descending' on __time) but no user-supplied orderBy list, Druid requires __time to be among the selected columns, since results are ordered by that column. The plain IllegalArgumentException is thrown in the constructor when orderBysFromUser is null but an implicit time ordering column is missing from columns.
Source
Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQuery.java:184
columnTypes.size()
);
}
}
final Pair<List<OrderBy>, Order> ordering = verifyAndReconcileOrdering(orderBysFromUser, orderFromUser);
this.orderBys = Preconditions.checkNotNull(ordering.lhs);
this.timeOrder = ordering.rhs;
if (this.columns != null && this.columns.size() > 0) {
// Validate orderBy. (Cannot validate when signature is empty, since that means "discover at runtime".)
for (final OrderBy orderByColumn : this.orderBys) {
if (!this.columns.contains(orderByColumn.getColumnName())) {
// Error message depends on how the user originally specified ordering.
if (orderBysFromUser != null) {
throw new IAE("Column [%s] from 'orderBy' must also appear in 'columns'.", orderByColumn.getColumnName());
} else {
throw new IllegalArgumentException("The __time column must be selected if the results are time-ordered.");
}
}
}
}
this.maxRowsQueuedForOrdering = validateAndGetMaxRowsQueuedForOrdering();
this.maxSegmentPartitionsOrderedInMemory = validateAndGetMaxSegmentPartitionsOrderedInMemory();
}
/**
* Verifies that the ordering of a query is solely determined by {@link #getTimeOrder()}. Required to actually
* execute queries, because {@link #getOrderBys()} is not yet understood by the query engines.
*
* @throws IllegalStateException if the ordering is not solely determined by {@link #getTimeOrder()}
*/
public static void verifyOrderByForNativeExecution(final ScanQuery query)
{
if (query.getTimeOrder() == Order.NONE && !query.getOrderBys().isEmpty()) {View on GitHub (pinned to 9b90983fd2)
Solutions
- Add "__time" to the columns list
- Remove the 'order' property from the query
- Set an explicit orderBy on a column that is selected
Example fix
// before
{"queryType":"scan","columns":["country"],"order":"ascending"}
// after
{"queryType":"scan","columns":["__time","country"],"order":"ascending"} Defensive patterns
Strategy: validation
Validate before calling
if (query.getOrder() != ScanQuery.Order.NONE && !query.getColumns().contains(ScanQuery.DRUID_TIMESTAMP_FIELD /* __time */) && query.getOrderBys().isEmpty()) {
throw new IllegalArgumentException("time-ordered scan requires __time in columns");
} Prevention
- Always include __time when using 'order':'ascending'/'descending'
- Prefer explicit orderBy over the legacy order field
- Add a lint rule for scan query JSON templates
When it happens
Trigger: Creating a ScanQuery with getTimeOrder() != NONE (order set via 'order' field) where columns does not contain __time and the user did not pass an explicit orderBy list.
Common situations: Queries requesting time-sorted scans with a projected column list that omits __time; older clients that assumed __time was always implicitly returned.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Column [%s] from 'orderBy' must also appear in 'columns'.
- Cannot provide 'order' incompatible with 'orderBy'
- Aggregation [%s] does not support column [%s] of type [%s].
- Cannot accept both 'splitPoints' and 'numBins'
- at least 2 bins expected
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/6868fd0e964cd7df.
Report an issue: GitHub.