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

  1. Inspect the physical plan with EXPLAIN to see why a GlobalShuffleExchange was paired with aggregate injection
  2. Fix the injector's precondition so it only runs on NodeToNodeExchange plans
  3. Return an explicit error variant instead of `unreachable!()`
  4. 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

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


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)