{"record":{"id":"9ef0fd49fa600c91","repo":"risingwavelabs/risingwave","slug":"incompatible-data-type-change-from-to-at","errorCode":null,"errorMessage":"incompatible data type change from {:?} to {:?} at path \"{}\"","messagePattern":"incompatible data type change from (.+?) to (.+?) at path \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/handler/create_table/col_id_gen.rs","lineNumber":206,"sourceCode":"                    path.push($segment);\n                    let ret = $block;\n                    path.pop();\n                    ret\n                }};\n            }\n\n            let original_column_id = match this.existing.get(&*path) {\n                Some((original_column_id, original_data_type)) => {\n                    // Only check the type name (discriminant) for compatibility check here.\n                    // For nested fields, we will check them recursively later.\n                    let incompatible = original_data_type.type_name() != data_type.type_name()\n                        || matches!(\n                            (original_data_type, &data_type),\n                            (DataType::Vector(old), DataType::Vector(new)) if old != new,\n                        );\n                    if incompatible {\n                        let path = path.iter().join(\".\");\n                        bail!(\n                            \"incompatible data type change from {:?} to {:?} at path \\\"{}\\\"\",\n                            original_data_type.type_name(),\n                            data_type.type_name(),\n                            path\n                        );\n                    }\n                    Some(*original_column_id)\n                }\n                None => None,\n            };\n\n            // Only top-level column and struct fields need an ID.\n            let need_gen_id = matches!(path.last().unwrap(), Segment::Field(_));\n\n            let new_id = if need_gen_id {\n                if let Some(id) = original_column_id {\n                    assert!(\n                        id != ColumnId::placeholder(),","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/handler/create_table/col_id_gen.rs#L188-L224","documentation":"`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.","triggerScenarios":"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)`.","commonSituations":"Altering struct fields to widen/narrow inner types; changing vector index dimensionality for embedding columns.","solutions":["Keep the inner type identical, or drop and re-add the column with the new nested type and backfill.","For Vector columns, keep the dimension and element type unchanged; create a new column for a different dimension.","Restructure the change as add-new-column + migrate + drop-old-column."],"exampleFix":"-- before (incompatible at path 'a')\nALTER TABLE t ALTER COLUMN s TYPE struct<a bigint>;\n-- after: add a new struct column instead\nALTER TABLE t ADD COLUMN s2 struct<a bigint>;\nUPDATE t SET s2 = ROW(s.a::bigint);\nALTER TABLE t DROP COLUMN s;\nALTER TABLE t RENAME COLUMN s2 TO s;","handlingStrategy":"validation","validationCode":"fn nested_types_compatible(orig: &DataType, new: &DataType) -> bool {\n    use DataType::*;\n    match (orig, new) {\n        (Struct(_), Struct(_)) => true,\n        (Vector(a), Vector(b)) => a == b,\n        (Struct(_), other) => other.contains_struct(),\n        _ => false,\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep inner struct field types stable when altering outer types","Never change Vector dimension in place","Prefer explicit new-column migration for nested type changes"],"tags":["rust","schema","alter-table","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}