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 = &req

View on GitHub (pinned to b5d8deb80c)

Solutions

  1. Finalize with the same aggregation request that produced the intermediate results.
  2. Keep engine versions consistent across all nodes handling the query.
  3. Do not map or rewrite intermediate bucket results between requests.
  4. 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

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


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