databendlabs/databend · error
block_meta_ref is ExchangeDeserializeMeta
Error message
block_meta_ref is ExchangeDeserializeMeta
What it means
TransformDeserializer::transform first checks that a block's meta downcasts to ExchangeDeserializeMeta, then re-downcasts it via downcast_from; the unreachable! fires only if the ownership-taking downcast unexpectedly fails after the reference check succeeded. In practice this message signals the meta check/double-downcast pairing was violated, i.e. a genuine code-level invariant bug rather than data-dependent failure.
Solutions
- Upgrade to a version where the deserializer downcast pairing is fixed
- Report with a stack trace; the fix is typically to use the checked reference directly instead of a second downcast
- If writing similar code, use the reference obtained from downcast_ref_from instead of re-downcasting after take
Example fix
// before
let Some(meta) = ExchangeDeserializeMeta::downcast_from(block_meta) else {
unreachable!("block_meta_ref is ExchangeDeserializeMeta");
};
// after
let meta = ExchangeDeserializeMeta::downcast_ref_from(block_meta_ref).expect("checked above"); Defensive patterns
Strategy: try-catch
Type guard
fn downcast_exchange_meta(m: &Arc<DataBlockMeta>) -> Option<&ExchangeDeserializeMeta> {
ExchangeDeserializeMeta::downcast_ref_from(m)
} Try / catch
catch Err(e) where message contains "block_meta_ref is ExchangeDeserializeMeta" -> gather stack trace and file bug; not recoverable at runtime.
Prevention
- Don't desynchronize the downcast_ref check and downcast_from take pair; use the checked reference directly
- Run clippy/tests after refactoring DataBlockMeta downcast helpers
- Keep exchange meta types in one module so check/take stay co-located
When it happens
Trigger: transform() takes meta that just passed ExchangeDeserializeMeta::downcast_ref_from but fails downcast_from — practically only from code changes that desynchronize the is_some() check and the take/downcast pair, or unusual meta layouts.
Common situations: Regressions after refactoring DataBlockMeta/downcast helpers in the exchange deserializer; never expected in production on stable code.
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
- unreachable!()
- _ => unreachable!()
- Internal, AggregateBucketScatter only recv Partitioned…
- unexpected aggregate meta
- [TRANSFORM-AGGREGATOR] Invalid hash table state during…
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/fef5a6f6fef68cd0.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/pipelines/processors/transforms/aggregator/serde/transform_deserializer.rs:246
mut meta: ExchangeDeserializeMeta,
) -> Result<Vec<DataBlock>> {
match meta.packet.pop().unwrap() {
DataPacket::FragmentData(v) => self.recv_data(meta.packet, v),
DataPacket::ErrorCode(err) => Err(err),
_ => unreachable!(),
}
}
}
impl AccumulatingTransform for TransformDeserializer {
const NAME: &'static str = "TransformDeserializer";
fn transform(&mut self, mut data_block: DataBlock) -> Result<Vec<DataBlock>> {
if let Some(block_meta_ref) = data_block.get_meta() {
if ExchangeDeserializeMeta::downcast_ref_from(block_meta_ref).is_some() {
let block_meta = data_block.take_meta().unwrap();
let Some(meta) = ExchangeDeserializeMeta::downcast_from(block_meta) else {
unreachable!("block_meta_ref is ExchangeDeserializeMeta");
};
if data_block.num_rows() != 0 {
return Err(ErrorCode::Internal("DataBlockMeta has rows"));
}
return self.transform_exchange_meta(meta);
}
}
Ok(vec![data_block])
}
}
pub type TransformAggregateDeserializer = TransformDeserializer;
View on GitHub (pinned to 288d84d76e)