quickwit-oss/tantivy · error

unexpected aggregation, expected term aggregation

Error message

unexpected aggregation, expected term aggregation

What it means

A panic in `into_final_bucket_result`: `IntermediateBucketResult::Terms` is being finalized with `req.agg.as_term().expect("unexpected aggregation, expected term aggregation")`, which fires when the request's aggregation is not a terms aggregation. The intermediate bucket result and the request definition disagree on aggregation type — an internal consistency violation rather than a user-input error.

Source

Thrown at src/aggregation/intermediate_agg_result.rs:694

                    limits,
                )?;

                let buckets = if histogram_req.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::Histogram { buckets })
            }
            IntermediateBucketResult::Terms { buckets: terms } => terms.into_final_result(
                req.agg
                    .as_term()
                    .expect("unexpected aggregation, expected term aggregation"),
                req.sub_aggregation(),
                limits,
            ),
            IntermediateBucketResult::Filter {
                doc_count,
                sub_aggregations,
            } => {
                // Convert sub-aggregation results to final format
                let final_sub_aggregations = sub_aggregations
                    .into_final_result(req.sub_aggregation().clone(), limits.clone())?;
                Ok(BucketResult::Filter(FilterBucketResult {
                    doc_count,
                    sub_aggregations: final_sub_aggregations,
                }))
            }
            IntermediateBucketResult::Composite { buckets } => {
                let composite_req = req
                    .agg

View on GitHub (pinned to b5d8deb80c)

Solutions

  1. Finalize with the exact request that produced the intermediate results.
  2. Ensure all nodes run compatible engine versions.
  3. Do not reorder or rewrite aggregation definitions before finalization.
  4. If you maintain the code, return an internal error via ok_or instead of expecting.

Example fix

// before
req.agg.as_term().expect("unexpected aggregation, expected term aggregation")
// after
req.agg.as_term()
    .ok_or_else(|| crate::AggregationError::Internal("expected term agg".to_string()))?
Defensive patterns

Strategy: validation

Validate before calling

fn is_term_agg(req: &Aggregation) -> bool {
    matches!(req, Aggregation::Term(_))
}
// guard before finalizing terms intermediates

Type guard

fn as_terms(req: &Aggregation) -> Option<&TermsAgg> {
    if let Aggregation::Term(t) = req { Some(t) } else { None }
}

Try / catch

let res = std::panic::catch_unwind(|| terms.into_final_result(req_agg, sub_agg, limits));
match res {
    Ok(r) => r,
    Err(_) => internal_error("expected term aggregation during finalization"),
}

Prevention

When it happens

Trigger: Finalizing a terms intermediate bucket result when the request resolved by aggregation path/id is not `Aggregation::Term` — e.g. distributed merge with mismatched aggregation trees, version skew, or intermediate results reused with a different request.

Common situations: Coordinator/node version mismatch in a cluster; incorrectly keyed caches of intermediate aggregation results; programmatic mutation of the request between search and finalization.

Related errors


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