{"record":{"id":"daf98a8ee006cc93","repo":"risingwavelabs/risingwave","slug":"duplicate-path","errorCode":null,"errorMessage":"duplicate path: {:?}","messagePattern":"duplicate path: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/handler/create_table/col_id_gen.rs","lineNumber":117,"sourceCode":"                        handle(existing, path, ColumnId::placeholder(), list.elem().clone());\n                    });\n                }\n                DataType::Map(map) => {\n                    // There's no id for the key/value as map's own structure won't change.\n                    with_segment!(Segment::MapKey, {\n                        handle(existing, path, ColumnId::placeholder(), map.key().clone());\n                    });\n                    with_segment!(Segment::MapValue, {\n                        handle(existing, path, ColumnId::placeholder(), map.value().clone());\n                    });\n                }\n\n                data_types::simple!() => {}\n            }\n\n            existing\n                .try_insert(path.clone(), (id, data_type))\n                .unwrap_or_else(|_| panic!(\"duplicate path: {:?}\", path));\n        }\n\n        let mut existing = Existing::new();\n\n        // Collect all existing fields into `existing`.\n        for col in original.columns() {\n            let mut path = vec![Segment::Field(col.name().to_owned())];\n            handle(\n                &mut existing,\n                &mut path,\n                col.column_id(),\n                col.data_type().clone(),\n            );\n        }\n\n        let version = original.version().expect(\"version field not set\");\n\n        Self {","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/handler/create_table/col_id_gen.rs#L99-L135","documentation":"Panic inside `Existing::try_insert` during column-id collection: the same fully-qualified column path (e.g. a nested struct field path) was encountered twice while gathering the columns of the table being altered. `Existing` is a map from column path to (column_id, data_type), and a duplicate path means the original schema contains two columns resolving to the identical nested path, which is an invariant violation.","triggerScenarios":"Calling ALTER TABLE (via `new_alter` -> `handle`) on a table whose original columns produce two identical paths — e.g. a nested struct field path collides with another column path after case/normalization, or a corrupted catalog storing two fields at the same path.","commonSituations":"Altering a table whose schema was mutated by another concurrent ALTER, restoring a table from a catalog snapshot with duplicated nested fields, or bugs in schema evolution producing two struct fields with the same name at the same nesting level.","solutions":["Inspect `SHOW CREATE TABLE` / the catalog for duplicate column or nested-field names and rename or drop one of them before altering.","Recreate the table (create new, INSERT from old, swap names) if the catalog is already corrupted.","If hit during development, add a uniqueness assertion when building the column list so the collision is caught at bind time instead of a panic."],"exampleFix":"// before: ALTER TABLE t ADD COLUMN v struct<a int> while a path collision exists\n// after: drop the conflicting column first\nALTER TABLE t DROP COLUMN v;\nALTER TABLE t ADD COLUMN v struct<a int>;","handlingStrategy":"validation","validationCode":"let mut seen = std::collections::HashSet::new();\nfor col in original.columns() {\n    // walk nested fields and collect paths; assert no duplicates before ALTER\n    if !seen.insert(col.name().to_string()) {\n        return Err(format!(\"duplicate column path: {}\", col.name()));\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure nested struct field names are unique within their level before altering","Avoid concurrent ALTERs on the same table","Rebuild catalogs through the normal create path rather than manual edits"],"tags":["rust","schema","panic","alter-table"],"backgroundTag":"internal-invariant-violation","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"}