apache/druid · error · QueryTimeoutException

Query timeout, cancelling pending results for query [%s]. Pe

Error message

Query timeout, cancelling pending results for query [%s]. Per-segment timeout exceeded.

What it means

When a per-segment future fails with an ExecutionException whose cause is a TimeoutException, waitForFutureCompletion rethrows it as QueryTimeoutException with the 'Per-segment timeout exceeded' message, distinguishing it from a whole-query timeout. The pending futures are cancelled first.

Source

Thrown at processing/src/main/java/org/apache/druid/query/groupby/epinephelinae/GroupByMergingQueryRunner.java:407

      }
    }
    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

  1. Increase the per-segment timeout in the query context (e.g. timeout-related context keys) or the overall timeout
  2. Investigate the slow segment: repurpose/compact it (smaller segments via compaction), warm its cache
  3. Add pre-filtering or reduce aggregation cardinality for the affected interval
  4. Check historical server health (GC pauses, disk IO) for that segment's host
  5. Re-run the query; if consistently hitting one segment, re-balance or compact

Example fix

// before
context: {"timeout":"300000"} // per-segment work exceeds limit
// after
context: {"timeout":"600000", "maxScatterGatherBytes": ...} // raise timeout + compact slow segments
Defensive patterns

Strategy: retry

Validate before calling

// before submitting: ensure per-segment timeout exceeds slowest segment scan estimate
if (slowestSegmentScanMs > perSegmentTimeoutMs) { raiseTimeoutOrCompactSegments(); }

Try / catch

try { runQuery(query); } catch (QueryTimeoutException e) { if (e.getMessage().contains("Per-segment timeout exceeded")) { compactSlowSegments(); retry(query); } else { throw e; } }

Prevention

When it happens

Trigger: Individual segment processing exceeded the per-segment timeout (query context perSegmentTimeout / segment-level TimeoutException from PrioritizedQueryRunnerCallable), wrapped into ExecutionException, detected in waitForFutureCompletion's catch block.

Common situations: One very large or cold-cached segment taking longer than the per-segment timeout; data skew where a single segment dominates runtime; per-segment timeout configured below realistic segment scan times.

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/a6ef7c8b05fcccb1. Report an issue: GitHub.