{"record":{"id":"62114159d37d8830","repo":"risingwavelabs/risingwave","slug":"version-field-not-set","errorCode":null,"errorMessage":"version field not set","messagePattern":"version field not set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/handler/create_table/col_id_gen.rs","lineNumber":133,"sourceCode":"            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 {\n            existing,\n            next_column_id: version.next_column_id,\n            version_id: version.version_id + 1,\n        }\n    }\n\n    /// Creates a new [`ColumnIdGenerator`] for a new table.\n    pub fn new_initial() -> Self {\n        Self {\n            existing: Existing::new(),\n            next_column_id: ColumnId::first_user_column(),\n            version_id: INITIAL_TABLE_VERSION_ID,\n        }\n    }\n\n    /// Generate [`ColumnId`]s for the given column and its nested fields (if any) recursively.","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/handler/create_table/col_id_gen.rs#L115-L151","documentation":"`ColumnCatalog::version()` returned `None` when `new_alter` builds the new `ColIdGenerator`, i.e. the original table's column catalog has no schema version (next_column_id / version_id) recorded. The generator needs the persisted version to compute the next column id and bumped version id, so a missing version is treated as a fatal invariant breach (expect/panic).","triggerScenarios":"ALTER TABLE on a table whose `ColumnCatalog` was constructed without a `version` field — e.g. a table created by legacy code paths or CDC/ingest paths that never set the version, then altered.","commonSituations":"Upgrading an old deployment whose tables were created before schema versioning was introduced, or hand-crafted test catalogs omitting `version`.","solutions":["Recreate the table so its catalog is rebuilt with a proper version field, then re-apply the ALTER.","Backfill/migrate the persisted column catalog to include the version field.","If this is a test fixture, construct the catalog via the normal create path so `version` is populated."],"exampleFix":"// before: catalog built manually without version\nlet catalog = ColumnCatalog::from(col_descs);\n// after: ensure version is set\nlet catalog = ColumnCatalog::from(col_descs).with_version(SchemaVersion::new(1));","handlingStrategy":"type-guard","validationCode":"if original.version().is_none() {\n    return Err(\"table catalog has no schema version; recreate the table\".into());\n}","typeGuard":"fn has_version(c: &ColumnCatalog) -> bool { c.version().is_some() }","tryCatchPattern":null,"preventionTips":["Create tables only through supported SQL paths that set the version field","Migrate legacy tables after upgrading before issuing ALTERs","In tests, build catalogs via the standard constructors"],"tags":["rust","schema","panic","alter-table"],"backgroundTag":"missing-required-config-field","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"}