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

  1. 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.
  2. Optimize the query (narrow intervals, add filters, reduce cardinality) so it finishes before the deadline.
  3. If the interrupt is unexpected, check broker logs for concurrent cancellations or shutdowns, and verify no other component interrupts the worker threads.
  4. 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

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


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)