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
- Remove the deprecated 'realtimeSegmentsOnly' key from the query context and keep only 'realtimeSegmentsMode'.
- If both keys come from different layers, find which client/template sets realtimeSegmentsOnly and update or delete it.
- Map the legacy boolean to the equivalent realtimeSegmentsMode enum value and express it purely via the mode key.
- 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
- Migrate all clients/templates off realtimeSegmentsOnly when upgrading
- Centralize query-context construction in one helper that rejects the legacy key
- Strip deprecated keys in a context-normalization layer before submitting queries
- Log when the legacy key is encountered so stragglers can be fixed
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
- Expected key [indexSpec] to be an indexSpec, but got
- Expected key [ ] to be a Boolean, but got [ ]
- Expected key [ ] to be a Float, but got [ ]
- Expected key [ ] to be a Granularity, but got [ ]
- Expected key [ ] to be a human readable number, but got [ ]
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)