apache/druid · error · QueryTimeoutException
Query[ ] url[ ] timed out.
Error message
Query[%s] url[%s] timed out.
What it means
Thrown by DirectDruidClient's response-queue dequeue() when polling for the next response chunk times out (queue.poll(checkQueryTimeout()) returns null). It signals that the query's overall timeout (query.getContext().getTimeout() bounded by druid.broker.http.readTimeout) elapsed while waiting for data from the data node, wrapped as QueryTimeoutException.
Solutions
- Increase the query timeout (context 'timeout' parameter) or the broker's druid.broker.http.readTimeout.
- Optimize the query (add filters, reduce intervals scanned, tune group-by buffers) to run within the timeout.
- Check historical node health (GC pauses, disk I/O, load) and scale if consistently slow.
- Retry the query; transient data-node slowness may have caused the stall.
Example fix
// before
query.getContext().put("timeout", "5000");
// after
query.getContext().put("timeout", "300000"); Defensive patterns
Strategy: try-catch
Try / catch
try {
return query.run(...);
} catch (QueryTimeoutException e) {
// optionally retry with a larger timeout once
log.warn("Query timed out on %s: %s", url, e.getMessage());
throw e;
} Prevention
- Size the context 'timeout' to the query's worst-case runtime.
- Keep druid.broker.http.readTimeout larger than the max query timeout.
- Monitor historical node latency and GC pauses.
- Alert on repeated query timeouts per datasource/interval.
When it happens
Trigger: Issuing a query whose context timeout expires before the historical/data node returns the first or a subsequent response chunk; slow historical nodes; very large scans with small timeout values; overloaded data nodes delaying the HTTP response.
Common situations: Heavy group-by/scan queries exceeding a low druid.broker.http.readTimeout; historical nodes swapping or GC-paused; network stalls between broker and historical; default query timeout lowered in context.
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
- Failed to initialize
- At most one of 'druid.broker.segment.watchedTiers' and…
- Exception while getting active tasks from Overlord. Will…
- If configured, 'druid.broker.segment.ignoredTiers' must be…
- If configured, 'druid.broker.segment.watchedTiers' must be…
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/fdde292a9a8bc08d.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/main/java/org/apache/druid/client/DirectDruidClient.java:228
// channel while it is being wound down.
if (discard.get()) {
return true;
}
// Increment queuedByteCount before queueing the object, so queuedByteCount is at least as high as
// the actual number of queued bytes at any particular time.
final InputStreamHolder holder = InputStreamHolder.fromChannelBuffer(buffer, chunkNum);
final long currentQueuedByteCount = queuedByteCount.addAndGet(holder.getLength());
queue.put(holder);
// True if we should keep reading.
return !usingBackpressure || currentQueuedByteCount < maxQueuedBytes;
}
private InputStream dequeue() throws InterruptedException
{
final InputStreamHolder holder = queue.poll(checkQueryTimeout(), TimeUnit.MILLISECONDS);
if (holder == null) {
throw new QueryTimeoutException(StringUtils.nonStrictFormat("Query[%s] url[%s] timed out.", query.getId(), url));
}
final long currentQueuedByteCount = queuedByteCount.addAndGet(-holder.getLength());
if (usingBackpressure && currentQueuedByteCount < maxQueuedBytes) {
long backPressureTime = Preconditions.checkNotNull(trafficCopRef.get(), "No TrafficCop, how can this be?")
.resume(holder.getChunkNum());
channelSuspendedTime.addAndGet(backPressureTime);
}
return holder.getStream();
}
@Override
public ClientResponse<InputStream> handleResponse(HttpResponse response, TrafficCop trafficCop)
{
trafficCopRef.set(trafficCop);
checkQueryTimeout();
checkTotalBytesLimit(response.getContent().readableBytes());View on GitHub (pinned to 9b90983fd2)