{"record":{"id":"891047e3be23e5dc","repo":"quickwit-oss/tantivy","slug":"unexpected-aggregation-expected-composite-aggrega","errorCode":null,"errorMessage":"unexpected aggregation, expected composite aggregation","messagePattern":"unexpected aggregation, expected composite aggregation","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/aggregation/intermediate_agg_result.rs","lineNumber":714,"sourceCode":"                limits,\n            ),\n            IntermediateBucketResult::Filter {\n                doc_count,\n                sub_aggregations,\n            } => {\n                // Convert sub-aggregation results to final format\n                let final_sub_aggregations = sub_aggregations\n                    .into_final_result(req.sub_aggregation().clone(), limits.clone())?;\n                Ok(BucketResult::Filter(FilterBucketResult {\n                    doc_count,\n                    sub_aggregations: final_sub_aggregations,\n                }))\n            }\n            IntermediateBucketResult::Composite { buckets } => {\n                let composite_req = req\n                    .agg\n                    .as_composite()\n                    .expect(\"unexpected aggregation, expected composite aggregation\");\n                buckets.into_final_result(composite_req, req.sub_aggregation(), limits)\n            }\n            IntermediateBucketResult::MultiTerms { buckets } => {\n                let multi_terms_req = req\n                    .agg\n                    .as_multi_terms()\n                    .expect(\"unexpected aggregation, expected multi_terms aggregation\");\n                buckets.into_final_result(multi_terms_req, req.sub_aggregation(), limits)\n            }\n        }\n    }\n\n    pub(crate) fn prune_intermediate_results(\n        &mut self,\n        req: &Aggregation,\n        mode: PruneMode,\n    ) -> crate::Result<()> {\n        match self {","sourceCodeStart":696,"sourceCodeEnd":732,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/aggregation/intermediate_agg_result.rs#L696-L732","documentation":"A panic in `into_final_bucket_result`: `IntermediateBucketResult::Composite` is finalized with `req.agg.as_composite().expect(\"unexpected aggregation, expected composite aggregation\")`, which fires when the request's aggregation is not a composite aggregation. This is the same family of request/intermediate-result type mismatches: the intermediate bucket result claims composite but the request definition does not.","triggerScenarios":"Finalizing composite aggregation intermediate results when `req.agg` resolves to a non-composite aggregation — mismatched aggregation ids during distributed merging, version-skewed nodes, or intermediate results paired with the wrong request.","commonSituations":"Rolling upgrades where shard responses follow a different intermediate format; cache hits returning intermediates from another query; custom tooling rebuilding the aggregation request tree.","solutions":["Use the original request object for finalization; never reuse intermediates across requests.","Keep all cluster nodes on the same engine version.","Verify the aggregation tree sent to shards matches the one used by the coordinator for finalization.","If you maintain the code, propagate an internal error via ok_or instead of expecting."],"exampleFix":"// before\nreq.agg.as_composite().expect(\"unexpected aggregation, expected composite aggregation\")\n// after\nreq.agg.as_composite()\n    .ok_or_else(|| crate::AggregationError::Internal(\"expected composite agg\".to_string()))?","handlingStrategy":"validation","validationCode":"fn is_composite_agg(req: &Aggregation) -> bool {\n    matches!(req, Aggregation::Composite(_))\n}\n// check before finalizing composite intermediates","typeGuard":"fn as_composite(req: &Aggregation) -> Option<&CompositeAgg> {\n    if let Aggregation::Composite(c) = req { Some(c) } else { None }\n}","tryCatchPattern":"let res = std::panic::catch_unwind(|| buckets.into_final_result(composite_req, sub_agg, limits));\nif res.is_err() {\n    return internal_error(\"expected composite aggregation during finalization\");\n}","preventionTips":["Finalize composite aggregations with the same request object that shards executed.","Do not rebuild the aggregation tree (rename/reorder aggs) mid-query.","Verify intermediate-result format compatibility across engine versions."],"tags":["rust","panic","aggregation","type-mismatch","internal-invariant"],"backgroundTag":"aggregation-type-mismatch","analyzedSha":"b5d8deb80c26924e6b007a5b1a7630f35ca64de4","analyzedAt":"2026-09-05T13:20:51.521Z","contentChangedAt":"2026-09-05T13:20:51.521Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}