apache/druid · error · ISE
Only PeriodGranulaity is supported for movingAverage queries
Error message
Only PeriodGranulaity is supported for movingAverage queries
What it means
MovingAverageQueryRunner.run only supports PeriodGranularity for the moving-average bucket computation, since it derives past buckets by applying the period to intervals. Any other granularity (e.g. duration or period-less granularities) reaches the else branch and throws IllegalStateException.
Source
Thrown at extensions-contrib/moving-average-query/src/main/java/org/apache/druid/query/movingaverage/MovingAverageQueryRunner.java:104
MovingAverageQuery maq = (MovingAverageQuery) query.getQuery();
List<Interval> intervals;
final Period period;
// Get the largest bucket from the list of averagers
Optional<Integer> opt =
maq.getAveragerSpecs().stream().map(AveragerFactory::getNumBuckets).max(Integer::compare);
int buckets = opt.orElse(0);
//Extend the interval beginning by specified bucket - 1
if (maq.getGranularity() instanceof PeriodGranularity) {
period = ((PeriodGranularity) maq.getGranularity()).getPeriod();
int offset = buckets <= 0 ? 0 : (1 - buckets);
intervals = maq.getIntervals()
.stream()
.map(i -> new Interval(i.getStart().withPeriodAdded(period, offset), i.getEnd()))
.collect(Collectors.toList());
} else {
throw new ISE("Only PeriodGranulaity is supported for movingAverage queries");
}
Sequence<Row> resultsSeq;
DataSource dataSource = maq.getDataSource();
if (maq.getDimensions() != null && !maq.getDimensions().isEmpty() &&
(dataSource instanceof TableDataSource || dataSource instanceof UnionDataSource ||
dataSource instanceof QueryDataSource)) {
// build groupBy query from movingAverage query
GroupByQuery.Builder builder = GroupByQuery.builder()
.setDataSource(dataSource)
.setInterval(intervals)
.setDimFilter(maq.getFilter())
.setGranularity(maq.getGranularity())
.setDimensions(maq.getDimensions())
.setAggregatorSpecs(maq.getAggregatorSpecs())
.setPostAggregatorSpecs(maq.getPostAggregatorSpecs())
.setContext(maq.getContext());
GroupByQuery gbq = builder.build();View on GitHub (pinned to 9b90983fd2)
Solutions
- Change the query granularity to a period-based one, e.g. {"type": "period", "period": "P1D"}
- Use ISO-8601 periods (PT1H, P7D) that match the desired averaging window
- If building the query programmatically, construct new PeriodGranularity(new Period(...), null, tz) instead of DurationGranularity
Example fix
// before
"granularity": {"type": "duration", "duration": 86400000}
// after
"granularity": {"type": "period", "period": "P1D", "timeZone": "UTC"} Defensive patterns
Strategy: validation
Validate before calling
Granularity g = maq.getGranularity();
if (!(g instanceof PeriodGranularity)) {
throw new IllegalArgumentException("movingAverage requires period granularity, got: " + g.getClass().getSimpleName());
} Type guard
boolean isPeriod(Granularity g) { return g instanceof PeriodGranularity; } Try / catch
try { results = runner.run(sequence, responseContext); } catch (IllegalStateException e) { if (e.getMessage().contains("PeriodGranulaity")) { /* rebuild query with period granularity */ } } Prevention
- Always use {"type":"period"} granularity in moving-average queries
- Convert duration granularities to ISO-8601 periods when translating queries
- Add schema checks in query submission tooling
When it happens
Trigger: Running a movingAverage/averager query whose 'granularity' is not a PeriodGranularity, e.g. {"type": "duration", "duration": 3600000} or a simple "day" string granularity.
Common situations: Users familiar with standard group-by queries reusing duration granularities in moving-average queries; SQL-generated or templated queries that always emit duration granularity; misconfigured dashboards.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot deserialize type[%s] to an RoaringBitmap64Counter:
- Can't load TrustStore. Truststore path or password is not se
- Unable to load TrustStore
- Duplicate output name[%s]
- druid.request.logging.transportUrl must be set when transpor
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/a912be29fe0b7ebe.
Report an issue: GitHub.