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

  1. Upgrade to a version where the deserializer downcast pairing is fixed
  2. Report with a stack trace; the fix is typically to use the checked reference directly instead of a second downcast
  3. 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

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


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)