apache/druid · error · BadQueryContextException
Expected key [%s] to be a Granularity, but got [%s]
Error message
Expected key [%s] to be a Granularity, but got [%s]
What it means
QueryContext.getGranularity parses a query context key into a Granularity (e.g. 'all', 'day', or a period string) using the object mapper. When the string cannot be deserialized to a Granularity, it throws QueryContexts.badTypeException declaring the key must be 'a Granularity'. The query fails during context validation.
Source
Thrown at processing/src/main/java/org/apache/druid/query/QueryContext.java:251
}
public <E extends Enum<E>> E getEnum(String key, Class<E> clazz, E defaultValue)
{
return QueryContexts.getAsEnum(key, get(key), clazz, defaultValue);
}
public Granularity getGranularity(String key, ObjectMapper jsonMapper)
{
final String granularityString = getString(key);
if (granularityString == null) {
return null;
}
try {
return jsonMapper.readValue(granularityString, Granularity.class);
}
catch (IOException e) {
throw QueryContexts.badTypeException(key, "a Granularity", granularityString);
}
}
public boolean isDebug()
{
return getBoolean(QueryContexts.ENABLE_DEBUG, QueryContexts.DEFAULT_ENABLE_DEBUG);
}
public boolean isBySegment()
{
return isBySegment(QueryContexts.DEFAULT_BY_SEGMENT);
}
public boolean isBySegment(boolean defaultValue)
{
return getBoolean(QueryContexts.BY_SEGMENT_KEY, defaultValue);
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Use a valid simple granularity string: 'second', 'minute', 'fifteen_minute', 'hour', 'day', 'week', 'month', 'quarter', 'year', or 'all'.
- For custom periods, pass a valid JSON duration granularity: {"type":"period","period":"P1D"}.
- Check the error message: it includes the offending value; fix the exact string you passed.
Example fix
// before
queryContext.put("timestampResultFieldGranularity", "daily");
// after
queryContext.put("timestampResultFieldGranularity", "day"); Defensive patterns
Strategy: validation
Validate before calling
Set<String> valid = Set.of("second","minute","fifteen_minute","thirty_minute","hour","day","week","month","quarter","year","all");
String g = (String) queryContext.get("timestampResultFieldGranularity");
if (g != null && !valid.contains(g.trim().toLowerCase()) && !g.trim().startsWith("{")) {
throw new IllegalArgumentException("Not a Granularity: " + g);
} Prevention
- Use canonical Granularity names ('day', 'hour'), never adjectives like 'daily'.
- For custom periods, use a duration-granularity JSON object ({"type":"period","period":"P1D"}).
- Validate context values with Granularity.fromString before issuing the query in custom tooling.
When it happens
Trigger: Setting a granularity-typed context key (e.g. timestampResultFieldGranularity) to a value like 'daily', 'dayly', or '1 day' that Jackson cannot map to Granularity; called from timestampResultFieldGranularity.
Common situations: Users confuse Granularity names with SQL interval syntax ('day' is valid, 'daily' and '7 days' are not), or pass a JSON object where a string like '{"type":"period","period":"P1D"}' with wrong fields is given.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Expected key [indexSpec] to be an indexSpec, but got [%s]
- unknown event type [%s]
- interrupted flushing elements from queue
- Cannot deserialize type[%s] to an RoaringBitmap64Counter:
- Failed to deserialize to RoaringBitmap64Counter, input is an
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/54c462d600e946e3.
Report an issue: GitHub.