databendlabs/databend · error
unreachable!()
Error message
unreachable!()
What it means
TransformAggregateSerializer::transform_input_data expects every non-empty input block to carry AggregateMeta::AggregatePayload so it can build a SerializeAggregateStream. If take_meta/downcast fails, the code calls unreachable!(), aborting because the serializer was fed a block shape it cannot serialize. It is a pipeline-internal invariant check, not user input validation.
Solutions
- Ensure all cluster nodes run the same Databend version and rerun the query
- Inspect the upstream transform feeding TransformAggregateSerializer to confirm it emits AggregatePayload meta
- If a custom pipeline is involved, only pass blocks with AggregateMeta::AggregatePayload to this serializer
- File a bug with query profile/plan if reproducible on identical versions
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check before the serializer transform
fn has_aggregate_payload(block: &DataBlock) -> bool {
block.get_meta()
.and_then(AggregateMeta::downcast_ref_from)
.map(|m| matches!(m, AggregateMeta::AggregatePayload(_)))
.unwrap_or(false)
} Type guard
fn as_aggregate_payload(m: Option<&Arc<DataBlockMeta>>) -> Option<&AggregatePayload> {
m.and_then(AggregateMeta::downcast_ref_from)
.and_then(|m| match m {
AggregateMeta::AggregatePayload(p) => Some(p),
_ => None,
})
} Try / catch
match res {
Err(e) if e.message().contains("unreachable") && pipeline_stage == "aggregate_serializer" => {
// abort query, verify node versions, file bug with stack trace
}
...
} Prevention
- Run homogeneous cluster versions during distributed aggregation
- Never insert custom transforms between partial aggregation and the serializer that alter meta
- Add a unit test asserting upstream blocks carry AggregatePayload meta
- Keep AggregateMeta enum refactors synchronized across serde transforms
When it happens
Trigger: event() -> transform_input_data receives a block whose meta is not AggregateMeta::AggregatePayload (e.g. it is Partitioned, spilled meta, or empty-with-wrong-meta), usually after pipeline rewiring, mixed cluster versions, or a bug in the transform upstream that attaches the wrong meta variant.
Common situations: Rolling upgrades with mismatched node versions exchanging aggregate payloads; custom transforms inserted between partial aggregation and the serializer; regressions from refactoring AggregateMeta enum variants.
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
- Internal, AggregateBucketScatter only recv Partitioned…
- block_meta_ref is ExchangeDeserializeMeta
- [TRANSFORM-AGGREGATOR] Invalid hash table state during…
- [TRANSFORM-AGGREGATOR] Invalid hash table state before spill
- [TRANSFORM-AGGREGATOR] Hash table already moved out
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/f858bccc60ef88c7.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/pipelines/processors/transforms/aggregator/serde/transform_aggregate_serializer.rs:123
if self.output_data.is_none() {
self.input_data = None;
}
}
Ok(())
}
}
impl TransformAggregateSerializer {
fn transform_input_data(&mut self, mut data_block: DataBlock) -> Result<Event> {
debug_assert!(data_block.is_empty());
let Some(AggregateMeta::AggregatePayload(p)) = data_block
.take_meta()
.and_then(AggregateMeta::downcast_from)
else {
unreachable!()
};
self.input_data = Some(SerializeAggregateStream::create(&self.params, p));
Ok(Event::Sync)
}
}
pub struct SerializeAggregateStream {
_params: Arc<AggregatorParams>,
payload: AggregatePayload,
flush_state: PayloadFlushState,
end_iter: bool,
nums: usize,
}
unsafe impl Send for SerializeAggregateStream {}
unsafe impl Sync for SerializeAggregateStream {}View on GitHub (pinned to 288d84d76e)