quickwit-oss/tantivy · error
unexpected metric type
Error message
unexpected metric type
What it means
A panic in `into_final_metric_result`: the intermediate result is `IntermediateMetricResult::Percentiles`, and the code asserts via `req.agg.as_percentile().expect(...)` that the corresponding request aggregation is a percentiles aggregation. The expect fires when the request's agg definition is a different metric type, meaning the intermediate metric result and its request definition are out of sync.
Source
Thrown at src/aggregation/intermediate_agg_result.rs:481
// buckets serialize as `"value": 0`, not `"value": null`.
// The non-ES `none_if_no_match` flag on `SumAggregation`
// opts into SQL-style `null` for downstream consumers.
let none_if_no_match = req
.agg
.as_sum()
.and_then(|sum| sum.none_if_no_match)
.unwrap_or(false);
let value = intermediate_sum.finalize();
if none_if_no_match {
MetricResult::Sum(value.into())
} else {
let value = Some(value.unwrap_or(0.0));
MetricResult::Sum(value.into())
}
}
IntermediateMetricResult::Percentiles(percentiles) => MetricResult::Percentiles(
percentiles
.into_final_result(req.agg.as_percentile().expect("unexpected metric type")),
),
IntermediateMetricResult::TopHits(top_hits) => {
MetricResult::TopHits(top_hits.into_final_result())
}
IntermediateMetricResult::Cardinality(cardinality) => {
MetricResult::Cardinality(cardinality.finalize().into())
}
}
}
pub(crate) fn get_value(&self, agg_property: &str) -> crate::Result<Option<f64>> {
match self {
IntermediateMetricResult::Average(avg) => Ok(avg.finalize()),
IntermediateMetricResult::Count(count) => Ok(count.finalize()),
IntermediateMetricResult::Max(max) => Ok(max.finalize()),
IntermediateMetricResult::Min(min) => Ok(min.finalize()),
IntermediateMetricResult::Stats(stats) => stats.finalize().get_value(agg_property),
IntermediateMetricResult::ExtendedStats(stats) => {View on GitHub (pinned to b5d8deb80c)
Solutions
- Ensure the aggregation request used for finalization is the exact request that produced the intermediate results.
- Verify cluster nodes run the same engine version (intermediate result format compatibility).
- Do not reuse or remap intermediate agg results across different requests or reordered aggregation trees.
- If you maintain the code, use `as_percentile().ok_or(...)` to return a typed error instead of panicking.
Example fix
// before
req.agg.as_percentile().expect("unexpected metric type")
// after
req.agg.as_percentile()
.ok_or_else(|| crate::AggregationError::Internal("expected percentiles agg".to_string()))? Defensive patterns
Strategy: validation
Validate before calling
// Verify the aggregation type in the request matches before finalizing percentiles results.
fn is_percentiles_agg(req: &Aggregation) -> bool {
matches!(req, Aggregation::Percentiles(_))
} Type guard
fn as_percentiles(req: &Aggregation) -> Option<&PercentilesAgg> {
if let Aggregation::Percentiles(p) = req { Some(p) } else { None }
} Try / catch
let res = std::panic::catch_unwind(|| intermediate.into_final_result(&req, limits));
match res {
Ok(r) => r,
Err(_) => return internal_error("intermediate/result type mismatch"),
} Prevention
- Always finalize with the exact request that produced the intermediate results.
- Keep engine versions uniform across the cluster.
- Never cache intermediate agg results without keying on the full request.
When it happens
Trigger: Converting intermediate aggregation results to final results when `req.agg` is not a percentile aggregation while the intermediate value is `IntermediateMetricResult::Percentiles` — caused by mismatched agg IDs, a corrupt aggregation tree, or results merged across incompatible request definitions.
Common situations: Distributed queries where nodes return intermediate results for a different aggregation layout than the coordinator's request; caching intermediate results keyed incorrectly; custom code reordering or rebuilding the aggregation request tree.
Related errors
- unexpected aggregation, expected histogram aggregation
- unexpected aggregation, expected range 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/03fa02696ab4da09.
Report an issue: GitHub.