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

  1. Ensure the aggregation request used for finalization is the exact request that produced the intermediate results.
  2. Verify cluster nodes run the same engine version (intermediate result format compatibility).
  3. Do not reuse or remap intermediate agg results across different requests or reordered aggregation trees.
  4. 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

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


AI-assisted analysis of quickwit-oss/tantivy@b5d8deb80c (2026-09-05). Data as JSON: /api/errors/03fa02696ab4da09. Report an issue: GitHub.