{"record":{"id":"bf3ee8165c243360","repo":"databendlabs/databend","slug":"internal-aggregatebucketscatter-only-recv-partiti","errorCode":null,"errorMessage":"Internal, AggregateBucketScatter only recv Partitioned AggregateMeta","messagePattern":"Internal, AggregateBucketScatter only recv Partitioned AggregateMeta","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/service/src/pipelines/processors/transforms/aggregator/serde/aggregate_scatter.rs","lineNumber":426,"sourceCode":"                                    .push(PartitionItem::BucketSpilled(payload));\n                            }\n                        }\n                    }\n\n                    chunks\n                        .into_iter()\n                        .map(|data| {\n                            AggregateMeta::Partitioned {\n                                bucket: None,\n                                data: PartitionedData::Mixed(data),\n                            }\n                            .into_datablock()\n                        })\n                        .collect()\n                }\n            },\n            _ => {\n                unreachable!(\"Internal, AggregateBucketScatter only recv Partitioned AggregateMeta\")\n            }\n        })\n    }\n}\n\nimpl FlightScatter for AggregateBucketScatter {\n    fn name(&self) -> &'static str {\n        \"Bucket\"\n    }\n\n    fn execute(&self, data_block: DataBlock) -> Result<Vec<DataBlock>> {\n        self.scatter(data_block, false)\n    }\n}\n\nimpl LocalScatter for AggregateBucketScatter {\n    fn name(&self) -> &'static str {\n        \"Bucket\"","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/service/src/pipelines/processors/transforms/aggregator/serde/aggregate_scatter.rs#L408-L444","documentation":"AggregateBucketScatter::scatter partitions an input block's AggregateMeta into per-bucket chunks for distributed two-phase aggregation. It only accepts blocks whose meta is AggregateMeta::Partitioned; any other meta variant hits this unreachable!(), meaning an upstream pipeline stage produced metadata the scatter stage was never designed to handle. This is an internal pipeline invariant, not a user-facing error.","triggerScenarios":"execute() is called with a DataBlock whose meta is not AggregateMeta::Partitioned — e.g. a plain ungrouped AggregateMeta, a wrong meta type, or a block with no meta — typically after a planner change, an older/newer cluster node serializing incompatible packets, or a custom pipeline wiring a non-partitioned block into a bucketed exchange.","commonSituations":"Mixed-version Databend clusters during rolling upgrade where query fragments disagree on meta format; custom source/pipeline code feeding the bucket scatter directly; bugs in the partial-aggregation transform that emit non-partitioned AggregateMeta.","solutions":["Check cluster node versions match (rolling upgrade completed) and rerun the query","Verify the upstream partial-aggregate/transform produces AggregateMeta::Partitioned before the bucketed exchange","If you wired a custom pipeline, only feed blocks whose meta was created via AggregateMeta::Partitioned","If reproducible on a single version, capture the query plan and file a bug with the query profile"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before feeding the scatter: verify meta kind\nfn is_partitioned_aggregate_meta(block: &DataBlock) -> bool {\n    block.get_meta()\n        .and_then(|m| AggregateMeta::downcast_ref_from(m))\n        .map(|m| matches!(m, AggregateMeta::Partitioned { .. }))\n        .unwrap_or(false)\n}","typeGuard":"fn ensure_partitioned(m: Option<&Arc<DataBlockMeta>>) -> Option<&AggregateMeta> {\n    m.and_then(AggregateMeta::downcast_ref_from)\n        .filter(|m| matches!(m, AggregateMeta::Partitioned { .. }))\n}","tryCatchPattern":"match res {\n    Err(e) if e.message().contains(\"AggregateBucketScatter only recv Partitioned\") => {\n        // log query profile, check cluster version skew, retry on homogeneous nodes\n    }\n    Err(e) => return Err(e),\n    Ok(v) => v,\n}","preventionTips":["Keep all cluster nodes on the same Databend version before running distributed aggregations","Don't wire arbitrary blocks into a bucketed exchange scatter; only Partitioned AggregateMeta blocks","After upgrading, rerun query regression tests on aggregation exchanges","When reproducing, capture the query plan/profile for the bug report"],"tags":["internal","distributed-query","aggregation","unreachable"],"backgroundTag":"internal-invariant-violation","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}