databendlabs/databend · error

_ => unreachable!()

Error message

_ => unreachable!()

What it means

TransformDeserializer::transform_exchange_meta unwraps packets from an ExchangeDeserializeMeta and handles only FragmentData and ErrorCode variants; anything else triggers unreachable!(). It encodes the invariant that exchange DataPackets between aggregation fragments contain only data fragments or error codes. Receiving a different packet kind means protocol mismatch between sender and receiver.

Solutions

  1. Align Databend versions across all nodes and retry the query
  2. Check whether the sender side emits a new DataPacket variant the receiver doesn't handle (version skew)
  3. File a bug if reproducible on matching versions, including the query that triggered it

Example fix

// before
match meta.packet.pop().unwrap() {
    DataPacket::FragmentData(v) => self.recv_data(meta.packet, v),
    DataPacket::ErrorCode(err) => Err(err),
    _ => unreachable!(),
}
// after
match meta.packet.pop().unwrap() {
    DataPacket::FragmentData(v) => self.recv_data(meta.packet, v),
    DataPacket::ErrorCode(err) => Err(err),
    other => Err(ErrorCode::Internal(format!("unexpected exchange packet: {other:?}"))),
}
Defensive patterns

Strategy: try-catch

Type guard

fn is_handled_packet(p: &DataPacket) -> bool {
    matches!(p, DataPacket::FragmentData(_) | DataPacket::ErrorCode(_))
}

Try / catch

match res {
    Err(e) if e.message().contains("unreachable") => {
        // check for mixed cluster versions; re-run after upgrade completes
    }
    ... 
}

Prevention

When it happens

Trigger: transform() processes an ExchangeDeserializeMeta whose packet vector contains a DataPacket variant other than FragmentData/ErrorCode (e.g. a control packet) — typically from mixed-version clusters or a sender pipeline stage emitting unsupported packet types.

Common situations: Cluster nodes on different versions exchanging serialized fragments; bugs in the exchange sender after DataPacket enum gained new variants without updating the deserializer; custom exchange implementations.

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/f7ca42d8df3547fa. Report an issue: GitHub.

Appendix: source

Thrown at src/query/service/src/pipelines/processors/transforms/aggregator/serde/transform_deserializer.rs:233

                    return Ok(vec![DataBlock::empty_with_meta(partitioned)]);
                }
            }
            other => Err(ErrorCode::Internal(format!(
                "Unknown aggregate serde meta type {other}"
            ))),
        }
    }
}

impl TransformDeserializer {
    fn transform_exchange_meta(
        &mut self,
        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"));
                }

View on GitHub (pinned to 288d84d76e)