databendlabs/databend · error

column view type mismatch

Error message

column view type mismatch

What it means

After the storage downcast succeeds, replace_typed downcasts the incoming BlockEntry to the handler's concrete ColumnView<T> and panics with this message if the entry's actual payload type differs from T. The storage and handler agreed, but the entry itself is the wrong type.

Solutions

  1. Cast or rebuild the entry as ColumnView<T> for the exact handler type before replacing.
  2. Ensure constant folding preserves the column's data type (apply a cast on the folded constant).
  3. Compare entry's type_id against T before calling replace_typed and take a conversion path instead.
  4. File a bug reproducing the query; indicates a missed cast in a rewrite rule.
Defensive patterns

Strategy: type-guard

Validate before calling

if !entry.downcast::<T>().is_ok_guard() /* i.e. downcast fails */ {
    entry = entry.cast_to::<T>()?;
}

Type guard

fn entry_is<T: AccessType>(entry: &BlockEntry) -> bool {
    entry.data_type() == &T::data_type()
}

Prevention

When it happens

Trigger: replace_typed receiving a BlockEntry built for a different value type than the TypeHandler's T — e.g. replacing a view computed with another scalar type after implicit conversion didn't happen.

Common situations: Constant replacement / fold-to-constant optimizations producing entries of a literal type (e.g. i64) into a column of another type (e.g. f64); cast elision bugs.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/ddabd7e37ffae30f. Report an issue: GitHub.

Appendix: source

Thrown at src/query/expression/src/block_vec.rs:448

            data: data as _,
        })
    }

    fn push_typed<T: AccessType>(storage: &mut ColumnStorage, entry: BlockEntry) -> Result<()> {
        let views = storage
            .data
            .downcast_mut::<Vec<ColumnView<T>>>()
            .expect("column view storage type mismatch");
        views.push(entry.downcast::<T>()?);
        Ok(())
    }

    fn replace_typed<T: AccessType>(storage: &mut ColumnStorage, index: usize, entry: BlockEntry) {
        let views = storage
            .data
            .downcast_mut::<Vec<ColumnView<T>>>()
            .expect("column view storage type mismatch");
        let view = entry.downcast::<T>().expect("column view type mismatch");
        views[index] = view;
    }

    fn handler_for(data_type: &DataType) -> TypeHandler {
        match data_type {
            DataType::Nullable(inner) => Self::handler_for_nullable(inner),
            _ => Self::handler_for_non_nullable(data_type),
        }
    }

    fn handler_for_non_nullable(data_type: &DataType) -> TypeHandler {
        match data_type {
            DataType::Null => TypeHandler::typed::<NullType>(false),
            DataType::EmptyArray => TypeHandler::typed::<EmptyArrayType>(false),
            DataType::EmptyMap => TypeHandler::typed::<EmptyMapType>(false),
            DataType::Boolean => TypeHandler::boolean(),
            DataType::Binary => TypeHandler::binary::<BinaryType>(),
            DataType::String => TypeHandler::string(),

View on GitHub (pinned to 288d84d76e)