apache/druid · error · BadQueryContextException

Configured timeout =

Error message

Configured timeout = %d is more than enforced limit of %d.

What it means

Druid allows operators to enforce a maximum query timeout (maxQueryTimeout, e.g. via druid.query.scheduler or server config). QueryContext.verifyMaxQueryTimeout compares the effective `timeout` in the query context against that enforced limit and throws BadQueryContextException when the caller asks for more timeout than the server permits. This is a server-side resource-protection guard, not a type or format error.

Solutions

  1. Lower the query's `timeout` context value to at or below the enforced limit reported in the message.
  2. If the larger timeout is legitimate, have the operator raise the enforced maxQueryTimeout server-side.
  3. Make clients discover the limit (config/endpoint) and clamp their requested timeout before submitting.
  4. Catch BadQueryContextException and surface the 'enforced limit of %d' value to the user so they can adjust.

Example fix

// before
context.put("timeout", 600_000L); // exceeds server limit of 300_000
// after
long requested = 600_000L;
long limit = 300_000L; // obtained from server config
context.put("timeout", Math.min(requested, limit));
Defensive patterns

Strategy: validation

Validate before calling

long requested = ((Number) query.getContext().getOrDefault("timeout", 0L)).longValue();
long enforcedLimit = /* from broker config */ 300_000L;
if (requested > enforcedLimit) {
    query.getContext().put("timeout", enforcedLimit);
}

Type guard

boolean withinTimeoutLimit(Object v, long limit) {
    return !(v instanceof Number) || ((Number) v).longValue() <= limit;
}

Try / catch

try {
    client.query(query);
} catch (BadQueryContextException e) {
    if (e.getMessage().contains("enforced limit of")) {
        long limit = parseEnforcedLimit(e.getMessage());
        query.getContext().put("timeout", limit);
        client.query(query);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling QueryContext.verifyMaxQueryTimeout(long maxQueryTimeout) when the context's `timeout` value exceeds the enforced limit, e.g. context has `{"timeout": 600000}` (10 min) while the server enforces max 300000 ms (5 min).

Common situations: Clients migrating from an unenforced cluster to one with a max-query-timeout cap; dashboards with hard-coded long timeouts; operators lowering the enforced limit without notifying query clients.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/e014c5d574ce027a. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/QueryContext.java:545

  {
    final long defaultTimeout = getLong(QueryContexts.DEFAULT_TIMEOUT_KEY, QueryContexts.DEFAULT_TIMEOUT_MILLIS);
    if (defaultTimeout >= 0) {
      return defaultTimeout;
    }
    throw new BadQueryContextException(
        StringUtils.format(
            "Timeout [%s] must be a non negative value, but was %d",
            QueryContexts.DEFAULT_TIMEOUT_KEY,
            defaultTimeout
        )
    );
  }

  public void verifyMaxQueryTimeout(long maxQueryTimeout)
  {
    long timeout = getTimeout();
    if (timeout > maxQueryTimeout) {
      throw new BadQueryContextException(
          StringUtils.format(
              "Configured %s = %d is more than enforced limit of %d.",
              QueryContexts.TIMEOUT_KEY,
              timeout,
              maxQueryTimeout
          )
      );
    }
  }

  public long getPerSegmentTimeout()
  {
    return getPerSegmentTimeout(QueryContexts.NO_TIMEOUT);
  }

  public long getPerSegmentTimeout(long defaultPerSegmentTimeout)
  {
    final long timeout = getLong(QueryContexts.PER_SEGMENT_TIMEOUT_KEY, defaultPerSegmentTimeout);

View on GitHub (pinned to 9b90983fd2)