risingwavelabs/risingwave · error

incompatible data type change from {:?} to {:?} at path "{}"

Error message

incompatible data type change from {:?} to {:?} at path "{}"

What it means

`ColIdGenerator::handle` detects an incompatible nested type change while reconciling original and new column trees: for paths where the type cannot be altered in place (non-compatible struct field changes, or differing `Vector` dimension/element types), it bails with both type names and the dotted path. This prevents silently producing a schema whose persisted rows cannot be decoded.

Source

Thrown at src/frontend/src/handler/create_table/col_id_gen.rs:206

                    path.push($segment);
                    let ret = $block;
                    path.pop();
                    ret
                }};
            }

            let original_column_id = match this.existing.get(&*path) {
                Some((original_column_id, original_data_type)) => {
                    // Only check the type name (discriminant) for compatibility check here.
                    // For nested fields, we will check them recursively later.
                    let incompatible = original_data_type.type_name() != data_type.type_name()
                        || matches!(
                            (original_data_type, &data_type),
                            (DataType::Vector(old), DataType::Vector(new)) if old != new,
                        );
                    if incompatible {
                        let path = path.iter().join(".");
                        bail!(
                            "incompatible data type change from {:?} to {:?} at path \"{}\"",
                            original_data_type.type_name(),
                            data_type.type_name(),
                            path
                        );
                    }
                    Some(*original_column_id)
                }
                None => None,
            };

            // Only top-level column and struct fields need an ID.
            let need_gen_id = matches!(path.last().unwrap(), Segment::Field(_));

            let new_id = if need_gen_id {
                if let Some(id) = original_column_id {
                    assert!(
                        id != ColumnId::placeholder(),

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Keep the inner type identical, or drop and re-add the column with the new nested type and backfill.
  2. For Vector columns, keep the dimension and element type unchanged; create a new column for a different dimension.
  3. Restructure the change as add-new-column + migrate + drop-old-column.

Example fix

-- before (incompatible at path 'a')
ALTER TABLE t ALTER COLUMN s TYPE struct<a bigint>;
-- after: add a new struct column instead
ALTER TABLE t ADD COLUMN s2 struct<a bigint>;
UPDATE t SET s2 = ROW(s.a::bigint);
ALTER TABLE t DROP COLUMN s;
ALTER TABLE t RENAME COLUMN s2 TO s;
Defensive patterns

Strategy: validation

Validate before calling

fn nested_types_compatible(orig: &DataType, new: &DataType) -> bool {
    use DataType::*;
    match (orig, new) {
        (Struct(_), Struct(_)) => true,
        (Vector(a), Vector(b)) => a == b,
        (Struct(_), other) => other.contains_struct(),
        _ => false,
    }
}

Prevention

When it happens

Trigger: ALTER TABLE changing a column type where at some nested path the original and new types differ incompatibly — e.g. `struct<a int>` to `struct<a bigint>` at path `a`, or `vector(3)` to `vector(4)`.

Common situations: Altering struct fields to widen/narrow inner types; changing vector index dimensionality for embedding columns.

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