apache/druid · error · QueryTimeoutException
Query [%s] timed out
Error message
Query [%s] timed out
What it means
The scan result iterator checks the query timeout on every next() call. When the current time reaches timeoutAt (derived from the query's timeout context), it throws QueryTimeoutException with the query id, aborting the scan. This enforces the 'timeout' query context parameter.
Source
Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQueryEngine.java:173
final int batchSize = query.getBatchSize();
return new Iterator<>()
{
private long offset = 0;
@Override
public boolean hasNext()
{
return !cursor.isDone() && offset < limit;
}
@Override
public ScanResultValue next()
{
if (!hasNext()) {
throw new NoSuchElementException();
}
if (hasTimeout && System.currentTimeMillis() >= timeoutAt) {
throw new QueryTimeoutException(StringUtils.nonStrictFormat("Query [%s] timed out", query.getId()));
}
final long lastOffset = offset;
final Object events;
final ScanQuery.ResultFormat resultFormat = query.getResultFormat();
if (ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST.equals(resultFormat)) {
events = rowsToCompactedList();
} else if (ScanQuery.ResultFormat.RESULT_FORMAT_LIST.equals(resultFormat)) {
events = rowsToList();
} else {
throw new UOE("resultFormat[%s] is not supported", resultFormat.toString());
}
responseContext.addRowScanCount(offset - lastOffset);
return new ScanResultValue(
segment.getId() == null ? null : segment.getId().toString(),
allColumns,
events,
rowSignatureBuilder.build()
);View on GitHub (pinned to 9b90983fd2)
Solutions
- Increase the 'timeout' value in the query context
- Reduce scan scope: add filters, fewer columns, or lower limit/scanRows
- Scale the historical tier or improve segment (column) caching
- Catch QueryTimeoutException client-side and retry with a larger timeout
Example fix
// before
{"queryType":"scan","context":{"timeout":1000},...}
// after
{"queryType":"scan","context":{"timeout":300000},...} Defensive patterns
Strategy: try-catch
Validate before calling
Long timeout = (Long) query.getContext().get("timeout");
if (timeout != null && timeout < expectedScanTimeMs) { /* raise or warn */ } Try / catch
try {
Sequence<ScanResultValue> seq = runner.run(QueryPlus.wrap(query), responseContext);
seq.toList();
} catch (QueryTimeoutException e) {
// retry with larger timeout or narrow the query
} Prevention
- Set realistic timeouts based on scan volume
- Bound scans with limit/scanRows and filters
- Monitor historical query latency and tune timeouts
When it happens
Trigger: Executing a scan query with a context timeout (hasTimeout true) whose execution exceeds the deadline; long scans over many segments with a small timeout value.
Common situations: Default low timeout in cluster config; large scans (millions of rows) exceeding client-set timeouts; slow disks or overloaded historicals making queries exceed the budget.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timeout [timeout] must be a non negative value, but was %d
- Per-segment timeout [timeoutPerSegmentQuery] must be a non n
- Resume command was not accepted within 5 seconds
- No such outputChannelMode[%s]
- Query interrupted
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/2f7ac98765ec57e5.
Report an issue: GitHub.