apache/druid · warning · QueryInterruptedException
Query interrupted
Error message
Query interrupted
What it means
BaseQuery.checkInterrupted() polls the thread's interrupt flag during query execution; if set, it throws QueryInterruptedException wrapping an InterruptedException. Druid uses this to cooperatively cancel queries whose deadlines expired, whose clients disconnected, or that were explicitly killed via the /druid/v2/{id} cancellation endpoint.
Solutions
- Determine whether the cancellation was intentional (timeout or explicit cancel) and increase the query 'timeout' context parameter or the HTTP scatter-gather limits if the query legitimately needs more time.
- Optimize the query (narrow intervals, add filters, reduce cardinality) so it finishes before the deadline.
- If the interrupt is unexpected, check broker logs for concurrent cancellations or shutdowns, and verify no other component interrupts the worker threads.
- Catch QueryInterruptedException at the API layer and map it to HTTP 429/500-style responses per the query lifecycle instead of treating it as a data error.
Example fix
// before
Map<String, Object> context = ImmutableMap.of();
// after
Map<String, Object> context = ImmutableMap.of("timeout", 600000); // raise timeout so checkInterrupted() isn't hit mid-query Defensive patterns
Strategy: try-catch
Validate before calling
// before submitting, sanity-check budgeted time
long remaining = deadline - System.currentTimeMillis();
if (remaining <= 0) {
throw new IllegalStateException("query deadline already expired; not submitting");
} Try / catch
try {
return queryClient.run(query).toList();
} catch (QueryInterruptedException e) {
if (e.getErrorCode().equals("Query interrupted") || e.getErrorCode().equals("Query timeout")) {
return retryWithBackoff(query.withOverriddenContext(ImmutableMap.of("timeout", largerTimeoutMs)));
}
throw e;
} Prevention
- Set an explicit 'timeout' context parameter sized for the query's data volume.
- Monitor for cancellation endpoint usage and client disconnects in broker logs.
- Narrow query intervals and add filters so queries complete well under deadlines.
- Treat interrupts as expected lifecycle events, not data errors, in client code.
When it happens
Trigger: A query thread calls BaseQuery.checkInterrupted() (or a runner calls it between segments/stages) after: the query's timeout elapsed, a client issued DELETE /druid/v2/{queryId}, the broker cancelled downstream futures, or something else called Thread.interrupt() on the worker thread.
Common situations: Long-running scans/groupBys hitting the configured timeout (e.g. druid.server.http.maxScatterGatherDurationMillis or timeout query context); users cancelling queries from the console; broker shutting down or dropping connections; oversubscribed clusters making queries exceed deadlines.
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.
Related errors
- Query interrupted
- url[ ] timed out
- Cache for node role [ ] could not be initialized before…
- Cache initialization for node role
- CanceledFault(CancellationReason.UNKNOWN)
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/b2129cb8a1ac89d4.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/query/BaseQuery.java:55
import org.joda.time.Interval;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
*
*/
@ExtensionPoint
public abstract class BaseQuery<T> implements Query<T>
{
public static void checkInterrupted()
{
if (Thread.interrupted()) {
throw new QueryInterruptedException(new InterruptedException());
}
}
public static final String QUERY_ID = "queryId";
public static final String SUB_QUERY_ID = "subQueryId";
public static final String SQL_QUERY_ID = "sqlQueryId";
private final DataSource dataSource;
private final QueryContext context;
private final QuerySegmentSpec querySegmentSpec;
private volatile Duration duration;
private final Granularity granularity;
public BaseQuery(
DataSource dataSource,
QuerySegmentSpec querySegmentSpec,
Map<String, Object> context
)
{View on GitHub (pinned to 9b90983fd2)