apache/druid · error · BadQueryContextException
Expected key [%s] to be an Integer, but got [%s]
Error message
Expected key [%s] to be an Integer, but got [%s]
What it means
QueryContexts.getAsInt(key, value) throws badTypeException with this message when the context value is neither null, a Number, nor a String — i.e. the type itself cannot even be attempted as an integer (Boolean, Map, List, etc.). Note this is distinct from the string-parse failure: here the value's class is simply wrong for an integer read.
Source
Thrown at processing/src/main/java/org/apache/druid/query/QueryContexts.java:383
} else if (value instanceof String) {
try {
return Numbers.parseInt(value);
}
catch (NumberFormatException ignored) {
// Attempt to handle trivial decimal values: 12.00, etc.
// This mimics how Jackson will convert "12.00" to a Integer on request.
try {
return new BigDecimal((String) value).intValueExact();
}
catch (Exception nfe) {
// That didn't work either. Give up.
throw badValueException(key, "in integer format", value);
}
}
}
throw badTypeException(key, "an Integer", value);
}
/**
* Get the value of a context value as an {@code int}. The value is expected
* to be {@code null}, a string or a {@code Number} object.
*/
public static int getAsInt(
final String key,
final Object value,
final int defaultValue
)
{
Integer val = getAsInt(key, value);
return val == null ? defaultValue : val;
}
@Nullable
public static Long getAsLong(String key, Object value)View on GitHub (pinned to 9b90983fd2)
Solutions
- Fix the query context JSON so the key holds a JSON number or numeric string.
- If building contexts in code, put an Integer/Long: context.put(key, 100).
- Verify the key name — a nested object under this key often means the config was placed under the wrong context key.
- Catch the exception and fall back to the default value for the context key.
Example fix
// before
{"maxScatterGatherBytes": {"bytes": 100}} // object -> IAE
// after
{"maxScatterGatherBytes": 100} Defensive patterns
Strategy: type-guard
Validate before calling
Object v = context.get(key);
if (v != null && !(v instanceof Number) && !(v instanceof String)) {
throw new IllegalArgumentException("Context key '" + key + "' must be numeric, got: " + v.getClass().getSimpleName());
} Type guard
boolean isContextNumber(Object v) { return v == null || v instanceof Number || v instanceof String; } Try / catch
try {
return query.getContextValue(key, defaultInt);
} catch (IllegalArgumentException e) {
LOG.warn(e, "Wrong type for context key [%s], using default", key);
return defaultInt;
} Prevention
- Never place booleans, arrays, or nested objects under integer-typed context keys.
- Use context.put(key, integerValue) with boxed numerics when building contexts in code.
- Sanitize client-provided context maps against a per-key expected-type table.
When it happens
Trigger: Calling QueryContexts.getAsInt(key, value) or query.getContextValue(key, int default) when the context map holds a Boolean, JSONArray, JSONObject, or other non-numeric, non-string object for an integer-typed context key.
Common situations: A client sends an integer context key as a JSON object or array (e.g. nested config pasted into the wrong key); a boolean flag accidentally placed under a numeric key; serialization frameworks that deserialized the value into a non-numeric type.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Expected key [%s] to be a String, but got [%s]
- Expected key [%s] to be a Boolean, but got [%s]
- Expected key [%s] to be in integer format, but got [%s]
- Expected key [%s] to be a Long, but got [%s]
- Expected key [%s] to be a Float, but got [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/02d9ee0611494b50.
Report an issue: GitHub.