apache/druid · error · BadQueryContextException

Cannot set both [realtimeSegmentsMode] and deprecated…

Error message

Cannot set both [realtimeSegmentsMode] and deprecated [realtimeSegmentsOnly]; use [realtimeSegmentsMode] only.

What it means

QueryContext validates that the new 'realtimeSegmentsMode' context key and the deprecated boolean 'realtimeSegmentsOnly' key are not both present. Because the old flag was superseded by the mode enum, setting both is ambiguous, so Druid throws BadQueryContextException rather than guessing precedence. This is an explicit configuration-conflict guard during query context parsing.

Solutions

  1. Remove the deprecated 'realtimeSegmentsOnly' key from the query context and keep only 'realtimeSegmentsMode'.
  2. If both keys come from different layers, find which client/template sets realtimeSegmentsOnly and update or delete it.
  3. Map the legacy boolean to the equivalent realtimeSegmentsMode enum value and express it purely via the mode key.
  4. Audit context construction code for both QueryContexts constants if you control the caller.

Example fix

// before
Map<String, Object> context = Map.of(
    QueryContexts.REALTIME_SEGMENTS_ONLY, true,
    QueryContexts.REALTIME_SEGMENTS_MODE, "AUTO"
);
// after
Map<String, Object> context = Map.of(
    QueryContexts.REALTIME_SEGMENTS_MODE, "AUTO"
);
Defensive patterns

Strategy: validation

Validate before calling

if (context.containsKey("realtimeSegmentsMode") && context.containsKey("realtimeSegmentsOnly")) {
  throw new IllegalArgumentException("Set only 'realtimeSegmentsMode'; 'realtimeSegmentsOnly' is deprecated");
}

Type guard

boolean hasConflictingContextKeys(Map<String, Object> ctx) {
  return ctx.get("realtimeSegmentsMode") != null && ctx.get("realtimeSegmentsOnly") != null;
}

Try / catch

try {
  QueryContext qctx = QueryContext.of(context);
} catch (BadQueryContextException e) {
  if (e.getMessage().contains("realtimeSegmentsOnly")) {
    context.remove("realtimeSegmentsOnly");
    qctx = QueryContext.of(context);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Submitting a query whose context map (or SQL query context parameters) contains both 'realtimeSegmentsMode' (any non-null value) and 'realtimeSegmentsOnly' (any non-null value). The check runs in QueryContext when resolving REALTIME_SEGMENTS_MODE.

Common situations: Clients built against older Druid versions still sending realtimeSegmentsOnly while the application was upgraded to also set realtimeSegmentsMode; dashboard/BI tools injecting the legacy flag on top of new context; copy-pasted query templates accumulating both keys.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


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

Appendix: source

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

    return getBoolean(QueryContexts.CTX_PREPLANNED, QueryContexts.DEFAULT_PREPLANNED);
  }

  /**
   * Returns the realtime segments mode for this query. If {@link QueryContexts#REALTIME_SEGMENTS_MODE} is absent
   * or null, falls back to the deprecated {@code realtimeSegmentsOnly} boolean: {@code true} maps
   * to {@link RealtimeSegmentsMode#EXCLUSIVE}; otherwise returns {@link RealtimeSegmentsMode#INCLUDE}.
   * Throws {@link BadQueryContextException} if both fields are set simultaneously.
   */
  public RealtimeSegmentsMode getRealtimeSegmentsMode()
  {
    RealtimeSegmentsMode mode = getEnum(
        QueryContexts.REALTIME_SEGMENTS_MODE,
        RealtimeSegmentsMode.class,
        null
    );
    boolean hasDeprecatedFlag = get(QueryContexts.REALTIME_SEGMENTS_ONLY) != null;
    if (mode != null && hasDeprecatedFlag) {
      throw new BadQueryContextException(
          StringUtils.format(
              "Cannot set both [%s] and deprecated [%s]; use [%s] only.",
              QueryContexts.REALTIME_SEGMENTS_MODE,
              QueryContexts.REALTIME_SEGMENTS_ONLY,
              QueryContexts.REALTIME_SEGMENTS_MODE
          )
      );
    }
    if (mode != null) {
      return mode;
    }
    if (hasDeprecatedFlag) {
      // Backward-compat: honour the deprecated realtimeSegmentsOnly flag.
      return getBoolean(QueryContexts.REALTIME_SEGMENTS_ONLY, QueryContexts.DEFAULT_REALTIME_SEGMENTS_ONLY)
             ? RealtimeSegmentsMode.EXCLUSIVE
             : QueryContexts.DEFAULT_REALTIME_SEGMENTS_MODE;
    }
    return QueryContexts.DEFAULT_REALTIME_SEGMENTS_MODE;

View on GitHub (pinned to 9b90983fd2)