apache/druid · error · BadQueryContextException

Timeout [maxDefaultTimeout] must be a non negative value, bu

Error message

Timeout [maxDefaultTimeout] must be a non negative value, but was %d

What it means

Druid validates the `defaultTimeout` query-context key, which supplies the fallback query timeout. QueryContext.getDefaultTimeout throws BadQueryContextException when the configured value is negative, because a negative default timeout would produce an invalid query deadline. The literal "maxDefaultTimeout" in the message template is just the message's fixed label; the offending value comes from the DEFAULT_TIMEOUT_KEY context entry.

Source

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

    );
  }

  @Nullable
  public Duration getTimeoutDuration()
  {
    if (hasTimeout()) {
      return Duration.ofMillis(getTimeout());
    }
    return null;
  }

  public long getDefaultTimeout()
  {
    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

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Set the `defaultTimeout` context value to a non-negative millisecond value or remove it so QueryContexts.DEFAULT_TIMEOUT_MILLIS applies.
  2. If you intend 'no timeout', omit the key rather than using -1.
  3. Audit config generation scripts/templates for negative sentinel values leaking into query context.
  4. Catch BadQueryContextException and re-raise with the offending context key so operators can fix config quickly.

Example fix

// before
context.put("defaultTimeout", -1); // 'unlimited' sentinel from another system
// after
// omit the key entirely, or use a valid positive value
context.put("defaultTimeout", 300_000L);
Defensive patterns

Strategy: validation

Validate before calling

Object dt = query.getContext().get("defaultTimeout");
if (dt instanceof Number && ((Number) dt).longValue() < 0) {
    throw new IllegalArgumentException("defaultTimeout must be non-negative, got " + dt);
}

Type guard

boolean isValidDefaultTimeout(Object v) {
    return !(v instanceof Number) || ((Number) v).longValue() >= 0;
}

Try / catch

try {
    client.query(query);
} catch (BadQueryContextException e) {
    if (e.getMessage().contains("defaultTimeout")) {
        query.getContext().remove("defaultTimeout");
        client.query(query); // retry with engine default
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling QueryContext.getDefaultTimeout() (via getTimeout() when no explicit timeout is set) when the context contains DEFAULT_TIMEOUT_KEY ("defaultTimeout") with a value < 0, e.g. `{"defaultTimeout": -1}`.

Common situations: Operators wiring a cluster- or tier-wide default timeout from config where a sentinel value like -1 (meaning 'unlimited' in some other system) was copied over; property-file mistakes; version changes where -1 semantics were never supported by Druid.

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