apache/druid · error

Query error, cancelling pending results for query [%s]

Error message

Query error, cancelling pending results for query [%s]

What it means

GroupByMergingQueryRunner logs this warning when a pending per-segment future completes exceptionally while merging group-by results from data nodes. The runner cancels all outstanding futures and rethrows the cause as a QueryException (QueryTimeoutException for timeouts). It indicates a per-segment query failed on a historical server while the merge was waiting for results.

Source

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

      for (AggregateResult result : results) {
        if (!result.isOk()) {
          GuavaUtils.cancelAll(true, future, futures);
          throw new ResourceLimitExceededException(result.getReason());
        }
      }
    }
    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. Inspect the underlying cause in the logged exception to find which segment/node failed
  2. Check historical node logs for the per-segment failure (OOM, segment corruption)
  3. Raise query timeout / per-segment timeout if the cause was a TimeoutException
  4. Retry the query; if a specific segment is corrupt, re-index or drop it

Example fix

// before: default per-segment timeout too small for heavy scans
// druid.query.groupBy.timeout=30000
// after: increase broker timeout config
// druid.query.timeout=300000; verify historical logs for segment-level failures
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call validation available; ensure timeouts configured
// druid.query.timeout and per-segment timeouts set generously before issuing group-by queries

Type guard

null

Try / catch

try { runner.run(...) } catch (QueryTimeoutException e) { /* retry with larger timeout / narrower interval */ } catch (QueryException e) { log.error("cause", e.getCause()); }

Prevention

When it happens

Trigger: A per-segment future passed to waitForFutureCompletion completes with an ExecutionException, e.g. a segment-level query threw on a historical node, or a nested per-segment future timed out (TimeoutException cause).

Common situations: Historical nodes failing on segment processing (OOM, corrupt segment, bad query on one segment), per-segment timeouts configured too low, network failures between broker and historials during a group-by merge.

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