databendlabs/databend · error
DataExchange::GlobalShuffleExchange(_) => unreachable!()
Error message
DataExchange::GlobalShuffleExchange(_) => unreachable!()
What it means
`AggregateExchangeInjector::flight_scatter` panics when it receives a `DataExchange::GlobalShuffleExchange`. Aggregate shuffle injection supports only `NodeToNodeExchange`; a global-shuffle exchange reaching this code means plan classification went wrong before injection.
Solutions
- Inspect the physical plan with EXPLAIN to see why a GlobalShuffleExchange was paired with aggregate injection
- Fix the injector's precondition so it only runs on NodeToNodeExchange plans
- Return an explicit error variant instead of `unreachable!()`
- Check Databend issue tracker/upstream fixes for global shuffle + aggregation planning
Example fix
// before
DataExchange::GlobalShuffleExchange(_) => unreachable!(),
// after
DataExchange::GlobalShuffleExchange(_) => Err(ErrorCode::Unimplemented("aggregate shuffle does not support GlobalShuffleExchange")), Defensive patterns
Strategy: validation
Validate before calling
if matches!(exchange, DataExchange::GlobalShuffleExchange(_)) { return Err(ErrorCode::Unimplemented("aggregate injection unsupported for GlobalShuffleExchange")); } Type guard
fn injectable(e: &DataExchange) -> bool { matches!(e, DataExchange::NodeToNodeExchange(_)) } Prevention
- Gate aggregate injection on plan exchange kind before calling flight_scatter
- Cover GlobalShuffleExchange aggregation plans in planner tests
- Prefer explicit error variants over unreachable!() in planning code
When it happens
Trigger: `flight_scatter` invoked on a plan whose exchange is `GlobalShuffleExchange`, i.e. the injector was applied to a globally-shuffled aggregation plan.
Common situations: Planner bugs where global shuffle plans (e.g. two-stage aggregation with global redistribute) are incorrectly treated as candidates for local aggregate shuffle injection.
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::Broadcast(_) => 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/df29f049c9bbce3b.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/pipelines/processors/transforms/aggregator/aggregate_exchange_injector.rs:66
) -> 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(
&self,View on GitHub (pinned to 288d84d76e)