{"record":{"id":"b2129cb8a1ac89d4","repo":"apache/druid","slug":"query-interrupted","errorCode":null,"errorMessage":"Query interrupted","messagePattern":"Query interrupted","errorType":"exception","errorClass":"QueryInterruptedException","httpStatus":null,"severity":"warning","filePath":"processing/src/main/java/org/apache/druid/query/BaseQuery.java","lineNumber":55,"sourceCode":"import org.joda.time.Interval;\n\nimport javax.annotation.Nullable;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n *\n */\n@ExtensionPoint\npublic abstract class BaseQuery<T> implements Query<T>\n{\n  public static void checkInterrupted()\n  {\n    if (Thread.interrupted()) {\n      throw new QueryInterruptedException(new InterruptedException());\n    }\n  }\n\n  public static final String QUERY_ID = \"queryId\";\n  public static final String SUB_QUERY_ID = \"subQueryId\";\n  public static final String SQL_QUERY_ID = \"sqlQueryId\";\n  private final DataSource dataSource;\n  private final QueryContext context;\n  private final QuerySegmentSpec querySegmentSpec;\n  private volatile Duration duration;\n  private final Granularity granularity;\n\n  public BaseQuery(\n      DataSource dataSource,\n      QuerySegmentSpec querySegmentSpec,\n      Map<String, Object> context\n  )\n  {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/BaseQuery.java#L37-L73","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nMap<String, Object> context = ImmutableMap.of();\n// after\nMap<String, Object> context = ImmutableMap.of(\"timeout\", 600000); // raise timeout so checkInterrupted() isn't hit mid-query","handlingStrategy":"try-catch","validationCode":"// before submitting, sanity-check budgeted time\nlong remaining = deadline - System.currentTimeMillis();\nif (remaining <= 0) {\n  throw new IllegalStateException(\"query deadline already expired; not submitting\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return queryClient.run(query).toList();\n} catch (QueryInterruptedException e) {\n  if (e.getErrorCode().equals(\"Query interrupted\") || e.getErrorCode().equals(\"Query timeout\")) {\n    return retryWithBackoff(query.withOverriddenContext(ImmutableMap.of(\"timeout\", largerTimeoutMs)));\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["query-execution","interruption","timeout","cancellation"],"backgroundTag":"request-timeout","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}