quickwit-oss/tantivy · error
unexpected aggregation, expected range aggregation
Error message
unexpected aggregation, expected range aggregation
What it means
A panic in `into_final_bucket_result` when reading the `keyed` flag of a range aggregation: `req.agg.as_range().expect("unexpected aggregation, expected range aggregation")` fails because the request's aggregation is not a range aggregation even though the intermediate result is. Like its siblings, this indicates the request definition and the intermediate bucket result have diverged.
Source
Thrown at src/aggregation/intermediate_agg_result.rs:649
req.agg
.as_range()
.expect("unexpected aggregation, expected histogram aggregation"),
range_res.column_type,
limits,
)
})
.collect::<crate::Result<Vec<_>>>()?;
buckets.sort_by(|left, right| {
left.from
.unwrap_or(f64::MIN)
.total_cmp(&right.from.unwrap_or(f64::MIN))
});
let is_keyed = req
.agg
.as_range()
.expect("unexpected aggregation, expected range aggregation")
.keyed;
let buckets = if is_keyed {
let mut bucket_map =
FxHashMap::with_capacity_and_hasher(buckets.len(), Default::default());
for bucket in buckets {
bucket_map.insert(bucket.key.to_string(), bucket);
}
BucketEntries::HashMap(bucket_map)
} else {
BucketEntries::Vec(buckets)
};
Ok(BucketResult::Range { buckets })
}
IntermediateBucketResult::Histogram {
is_date_agg,
buckets,
} => {
let histogram_req = &reqView on GitHub (pinned to b5d8deb80c)
Solutions
- Finalize with the same aggregation request that produced the intermediate results.
- Keep engine versions consistent across all nodes handling the query.
- Do not map or rewrite intermediate bucket results between requests.
- If you maintain the code, convert the expect into a propagated internal error.
Example fix
// before
req.agg.as_range().expect("unexpected aggregation, expected range aggregation").keyed
// after
req.agg.as_range()
.ok_or_else(|| crate::AggregationError::Internal("expected range agg".to_string()))?.keyed Defensive patterns
Strategy: validation
Validate before calling
fn is_range_agg(req: &Aggregation) -> bool {
matches!(req, Aggregation::Range(_))
}
// guard before reading .keyed Type guard
fn range_keyed(req: &Aggregation) -> Option<bool> {
if let Aggregation::Range(r) = req { Some(r.keyed) } else { None }
} Try / catch
let res = std::panic::catch_unwind(|| into_final_bucket_result(intermediate, &req, limits));
match res {
Ok(b) => b,
Err(_) => internal_error("expected range aggregation during finalization"),
} Prevention
- Pass the original request object through to finalization.
- Avoid replaying cached intermediate bucket results against different requests.
- Keep node versions in lockstep during rolling upgrades.
When it happens
Trigger: Finalizing range aggregation results when the request resolved via `req.agg` is not an `Aggregation::Range` — typically from agg-id mismatches in distributed result merging, or reusing intermediate results with a different request.
Common situations: Version-skewed cluster nodes producing/consuming different intermediate formats; incorrect caching of intermediate agg results; test or plugin code constructing mismatched (request, intermediate) pairs.
Related errors
- unexpected metric type
- unexpected aggregation, expected histogram aggregation
- unexpected aggregation, expected term aggregation
- unexpected aggregation, expected composite aggregation
- TermMissingAgg collector, but no missing found in agg req
AI-assisted analysis of quickwit-oss/tantivy@b5d8deb80c (2026-09-05).
Data as JSON: /api/errors/72ed7356fe6e1ce4.
Report an issue: GitHub.