risingwavelabs/risingwave · error · MetaError

Column type mismatch

Error message

Column type mismatch: {:?} != {:?}

What it means

During cdc/table schema comparison the code checks each corresponding column pair's types with `equals_datatype`; on mismatch it returns "Column type mismatch: {:?} != {:?}" naming the source (`from`) and target (`to`) types. This enforces that schema evolution between the compared relations keeps column types identical.

Solutions

  1. Alter the target table so its column type matches the source column type shown in the error (both types are printed in order).
  2. Recreate the downstream table/sink with the correct schema if the type cannot be altered in place.
  3. Align connector/source type mappings (or upgrade the connector) so upstream types map to the same DataType as the target.
  4. Compare the two `DataType` debug dumps in the message to pinpoint the differing column and update your migration scripts.

Example fix

-- before: source column widened but target not migrated
-- from: Integer, to: Varchar
ALTER TABLE t ALTER COLUMN c TYPE integer;
-- after: target matches source type
Defensive patterns

Strategy: validation

Validate before calling

fn assert_columns_compatible(from: &[Column], to: &[Column]) -> Result<(), String> {
    for (f, t) in from.iter().zip(to) {
        if !f.data_type.equals_datatype(&t.data_type) {
            return Err(format!("column {} : {:?} != {:?}", f.name, f.data_type, t.data_type));
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: Executing the schema-compatibility path (e.g. CDC table schema sync/upsert in utils.rs) when a column exists on both sides but its DataType differs — for example VARCHAR vs INT, or differing struct field types.

Common situations: Upstream schema changed (ALTER TABLE at the source) while the target table was not migrated; a source connector reports a different type mapping after a version change; hand-edited or drifted table schemas in dev environments.

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 risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/704ad4c31810a247. Report an issue: GitHub.

Appendix: source

Thrown at src/meta/src/controller/utils.rs:2529

        .map(|(idx, col)| (col.column_desc.as_ref().unwrap().column_id, idx))
        .collect::<HashMap<_, _>>();

    for to_col in to {
        let to_col = to_col.column_desc.as_ref().unwrap();
        let to_col_type_ref = to_col.column_type.as_ref().unwrap();
        let to_col_type = DataType::from(to_col_type_ref);
        if let Some(from_idx) = idx_by_col_id.get(&to_col.column_id) {
            let from_col_type = DataType::from(
                from[*from_idx]
                    .column_desc
                    .as_ref()
                    .unwrap()
                    .column_type
                    .as_ref()
                    .unwrap(),
            );
            if !to_col_type.equals_datatype(&from_col_type) {
                return Err(anyhow!(
                    "Column type mismatch: {:?} != {:?}",
                    from_col_type,
                    to_col_type
                )
                .into());
            }
            exprs.push(PbExprNode {
                function_type: expr_node::Type::Unspecified.into(),
                return_type: Some(to_col_type_ref.clone()),
                rex_node: Some(expr_node::RexNode::InputRef(*from_idx as _)),
            });
        } else {
            let to_default_node =
                if let Some(GeneratedOrDefaultColumn::DefaultColumn(DefaultColumnDesc {
                    expr,
                    ..
                })) = &to_col.generated_or_default_column
                {

View on GitHub (pinned to 6469eb736d)