databendlabs/databend · error
DataExchange::Broadcast(_) => unreachable!()
Error message
DataExchange::Broadcast(_) => unreachable!()
What it means
`AggregateExchangeInjector::flight_scatter` panics when it receives a `DataExchange::Broadcast` exchange. Broadcast exchanges fan a block to all nodes and are incompatible with aggregate shuffle injection, which only applies to node-to-node shuffles of the aggregated partial state.
Solutions
- Use EXPLAIN to inspect the exchange chosen for the aggregation in the failing query
- Report/check for planner regressions where aggregate injection was applied to broadcast exchanges
- Convert the panic into a planner error to fail the query gracefully
- Upgrade Databend to get planner fixes for exchange-injection classification
Example fix
// before
DataExchange::Broadcast(_) => unreachable!(),
// after
DataExchange::Broadcast(_) => Err(ErrorCode::Unimplemented("aggregate shuffle does not support Broadcast exchange")), Defensive patterns
Strategy: validation
Validate before calling
if matches!(exchange, DataExchange::Broadcast(_)) { return Err(ErrorCode::Unimplemented("aggregate injection unsupported for Broadcast")); } Type guard
fn is_shuffle_exchange(e: &DataExchange) -> bool { matches!(e, DataExchange::NodeToNodeExchange(_)) } Prevention
- Verify the optimizer never pairs broadcast exchanges with aggregate injection
- Add plan-level assertions in tests for aggregation over broadcast inputs
- Return typed planner errors for unsupported exchange kinds
When it happens
Trigger: `flight_scatter` is called with a `DataExchange::Broadcast` plan fragment, meaning aggregate injection was attempted on a broadcast-distribution plan.
Common situations: Optimizer bug in exchange planning for distributed aggregation; queries whose GROUP BY pattern unexpectedly planned a broadcast exchange where a shuffle was expected.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- DataExchange::Merge(_) => unreachable!()
- DataExchange::GlobalShuffleExchange(_) => unreachable!()
- grouping function must be rewritten in type_checker, but got
- AggregateMeta does not support exchanging between multiple…
- _ => unreachable!()
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/94797a418a14ef85.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/pipelines/processors/transforms/aggregator/aggregate_exchange_injector.rs:65
shuffle_mode: AggregateShuffleMode,
) -> Arc<dyn ExchangeInjector> {
Arc::new(AggregateInjector {
ctx,
aggregator_params: params,
shuffle_mode,
})
}
}
impl ExchangeInjector for AggregateInjector {
fn flight_scatter(
&self,
_: &Arc<QueryContext>,
exchange: &DataExchange,
) -> Result<Arc<Box<dyn FlightScatter>>> {
match exchange {
DataExchange::Merge(_) => unreachable!(),
DataExchange::Broadcast(_) => unreachable!(),
DataExchange::GlobalShuffleExchange(_) => unreachable!(),
DataExchange::NodeToNodeExchange(exchange) => match self.shuffle_mode {
AggregateShuffleMode::Row => Ok(Arc::new(Box::new(AggregateRowScatter {
buckets: exchange.destination_ids.len(),
aggregate_params: self.aggregator_params.clone(),
}))),
AggregateShuffleMode::Bucket(_) => Ok(Arc::new(Box::new(AggregateBucketScatter {
buckets: exchange.destination_ids.len(),
}))),
},
}
}
fn exchange_sorting(&self) -> Option<Arc<dyn ExchangeSorting>> {
None
}
fn apply_merge_serializer(View on GitHub (pinned to 288d84d76e)