apache/druid · error · IllegalStateException
Cannot call get() before aggregate()
Error message
Cannot call get() before aggregate()
What it means
PassthroughAggregator.get() is a state guard: the aggregator buffers the selected object in aggregate() (setting didSet), and get() before any aggregate() call would return an uninitialized value, so it throws ISE. Indicates the aggregation framework finalized/read the aggregator out of order.
Solutions
- Report as a bug with the query and aggregator configuration; the framework should always call aggregate() before get().
- Check whether custom aggregator code or an unusual query shape (e.g. empty result rows) reaches get() before aggregation.
Example fix
// before
Object v = agg.get(); // ISE if never aggregated
// after
if (agg instanceof PassthroughAggregator) { agg.aggregate(); }
Object v = agg.get(); Defensive patterns
Strategy: type-guard
Validate before calling
// aggregate at least once before reading
if (rows.isEmpty()) { throw new IllegalStateException("No rows; aggregator never aggregated"); } Type guard
// can only be checked post-aggregation; ensure lifecycle
boolean canGet(PassthroughAggregator a) { a.aggregate(); return true; } Try / catch
try {
Object v = aggregator.get();
} catch (ISE e) {
if (e.getMessage().contains("before aggregate")) { /* aggregate first or treat as no data */ }
else throw e;
} Prevention
- Always call aggregate() (driven by at least one row) before get()
- In tests, initialize the selector and call aggregate() in setup
- Handle empty-input groups explicitly
When it happens
Trigger: Query engine or test code calls get()/getFloat()/etc. before invoking aggregate() at least once on the aggregator instance.
Common situations: Custom aggregation code or a unit test retrieving the result of an aggregator that never aggregated; engine bug where the aggregator was never driven.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/0cf573e56e8e796b.
Report an issue: GitHub.
Appendix: source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/util/PassthroughAggregator.java:55
}
@Override
public void aggregate()
{
if (didSet) {
throw new ISE("Cannot set twice");
}
val = selector.getObject();
didSet = true;
}
@Nullable
@Override
public Object get()
{
if (!didSet) {
throw new ISE("Cannot call get() before aggregate()");
}
return val;
}
@Override
public float getFloat()
{
throw new UnsupportedOperationException();
}
@Override
public long getLong()
{
throw new UnsupportedOperationException();
}
@OverrideView on GitHub (pinned to 9b90983fd2)