apache/druid · error · QueryTimeoutException
Query [%s] timed out
Error message
Query [%s] timed out
What it means
waitForFutureCompletion waits on the merging query runner's futures for the configured query timeout. On QueryTimeoutException or TimeoutException it cancels the outstanding per-segment futures and throws QueryTimeoutException('Query [id] timed out'), surfacing the broker/timeout chain to the caller.
Source
Thrown at processing/src/main/java/org/apache/druid/query/groupby/epinephelinae/GroupByMergingQueryRunner.java:399
final List<AggregateResult> results = hasTimeout ? future.get(timeout, TimeUnit.MILLISECONDS) : future.get();
for (AggregateResult result : results) {
if (!result.isOk()) {
GuavaUtils.cancelAll(true, future, futures);
throw new ResourceLimitExceededException(result.getReason());
}
}
}
catch (InterruptedException | CancellationException e) {
log.noStackTrace().warn(e, "Query interrupted, cancelling pending results for query [%s]", query.getId());
GuavaUtils.cancelAll(true, future, futures);
throw new QueryInterruptedException(e);
}
catch (QueryTimeoutException | TimeoutException e) {
log.noStackTrace().warn(e, "Query timeout, cancelling pending results for query [%s]", query.getId());
GuavaUtils.cancelAll(true, future, futures);
throw new QueryTimeoutException(StringUtils.nonStrictFormat("Query [%s] timed out", query.getId()));
}
catch (ExecutionException e) {
log.noStackTrace().warn(e, "Query error, cancelling pending results for query [%s]", query.getId());
GuavaUtils.cancelAll(true, future, futures);
Throwable cause = e.getCause();
// Nested per-segment future timeout
if (cause instanceof TimeoutException) {
throw new QueryTimeoutException(StringUtils.nonStrictFormat("Query timeout, cancelling pending results for query [%s]. Per-segment timeout exceeded.", query.getId()));
}
throw new RuntimeException(e);
}
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Raise the query timeout (timeout field in the query context / druid.query.defaultTimeout)
- Optimize the query: narrow intervals, add filters, reduce dimensions/aggregators, enable query caching
- Scale historicals (more cores/memory) or raise druid.processing.numThreads
- Check for skewed/slow segments and broker queue wait times in metrics (query/time, query/wait/time)
- Split the query into smaller time chunks and merge client-side
Example fix
// before
{"queryType":"groupBy", "intervals":["2010/2026"], ...} // exceeds default timeout
// after
{"queryType":"groupBy", "intervals":["2025/2026"], "context":{"timeout":"1800000"}, ...} // narrower range + explicit timeout Defensive patterns
Strategy: retry
Validate before calling
long estMillis = estimateScanTime(query); // compare against configured timeout before submitting
if (estMillis > timeoutMs) { narrowIntervalsOrRaiseTimeout(); } Try / catch
try { runQuery(query); } catch (QueryTimeoutException e) { if (e.getMessage().endsWith("timed out")) { retryWithLargerTimeout(narrow(query)); } else { throw e; } } Prevention
- Set explicit query timeouts matching workload SLAs
- Monitor query/wait/time metrics to size thread pools
- Keep intervals narrow and enable caching for repeated queries
When it happens
Trigger: A groupBy query's per-segment or overall futures do not complete within the configured timeout (query.getConfig().getTimeout() / PrioritizedExecutorTask queue wait), so waitForFutureCompletion (invoked from apply or make) cancels and throws.
Common situations: Heavy groupBy queries with huge cardinality; undersized processing thread pools; slow historicals (disk, GC); default 5-minute timeout exceeded; timeouts on large multi-interval scans.
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
- Query timeout, cancelling pending results for query [%s]. Pe
- Null queryRunner! Looks to be some segment unmapping action
- Resume command was not accepted within 5 seconds
- Query interrupted
- Timeout [timeout] must be a non negative value, but was %d
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/1f50f25a78024a9c.
Report an issue: GitHub.