apache/druid · error · BadQueryContextException
Expected key [%s] to be a Long, but got [%s]
Error message
Expected key [%s] to be a Long, but got [%s]
What it means
QueryContexts.getAsLong(key, value) throws badTypeException with this message when the context value's class cannot be interpreted as a Long at all — it is neither null, a Number, nor a String (e.g. Boolean, Map, List). The exception includes the key and the value's actual type.
Source
Thrown at processing/src/main/java/org/apache/druid/query/QueryContexts.java:424
return ((Number) value).longValue();
} else if (value instanceof String) {
try {
return Numbers.parseLong(value);
}
catch (NumberFormatException ignored) {
// Attempt to handle trivial decimal values: 12.00, etc.
// This mimics how Jackson will convert "12.00" to a Long on request.
try {
return new BigDecimal((String) value).longValueExact();
}
catch (Exception nfe) {
// That didn't work either. Give up.
throw badValueException(key, "in long format", value);
}
}
}
throw badTypeException(key, "a Long", value);
}
/**
* Get the value of a context value as an {@code long}. The value is expected
* to be {@code null}, a string or a {@code Number} object.
*/
public static long getAsLong(
final String key,
final Object value,
final long defaultValue
)
{
Long val = getAsLong(key, value);
return val == null ? defaultValue : val;
}
/**
* Get the value of a context value as an {@code Float}. The value is expectedView on GitHub (pinned to 9b90983fd2)
Solutions
- Correct the context JSON so the key holds a JSON number or numeric string.
- In code, put a Long/Integer: context.put(key, 123456789L).
- Check for key-name typos that cause a value of the wrong shape to land under this key.
- Catch the exception and fall back to the default value.
Example fix
// before
{"timeout": false} // boolean under numeric key -> IAE
// after
{"timeout": 30000} 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, defaultLong);
} catch (IllegalArgumentException e) {
LOG.warn(e, "Wrong type for context key [%s], using default", key);
return defaultLong;
} Prevention
- Keep boolean flags and numeric limits under distinct, correctly named context keys.
- Validate deserialized context maps before handing them to query execution.
- Use typed context builders rather than raw Map<String, Object> puts.
When it happens
Trigger: Calling QueryContexts.getAsLong(key, value) or query.getContextValue(key, long default) when the context map stores a Boolean, JSON object/array, or other non-numeric non-string object under a long-typed context key.
Common situations: A boolean or nested-config value placed under a numeric key by mistake; clients sending JSON objects where a number is expected; earlier code paths that stored raw deserialized JSON trees into the context.
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 an Integer, but got [%s]
- Expected key [%s] to be in long format, 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/cfbce57e8dea0bee.
Report an issue: GitHub.