{"record":{"id":"4b5cc8caea9fd8e9","repo":"risingwavelabs/risingwave","slug":"failed-to-decode-persisted-defaultcolumndesc","errorCode":null,"errorMessage":"failed to decode persisted `DefaultColumnDesc`","messagePattern":"failed to decode persisted `DefaultColumnDesc`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/handler/create_table.rs","lineNumber":353,"sourceCode":"                            column.name\n                        ))\n                        .into());\n                    }\n                }\n                ColumnOption::DefaultValueInternal { persisted, expr: _ } => {\n                    // When a `DEFAULT INTERNAL` is used internally for schema change, the persisted value\n                    // should already be set during purifcation. So if we encounter an empty value here, it\n                    // means the user has specified it explicitly in the SQL statement, typically by\n                    // directly copying the result of `SHOW CREATE TABLE` and executing it.\n                    if persisted.is_empty() {\n                        bail_bind_error!(\n                            \"DEFAULT INTERNAL is only used for internal purposes, \\\n                             please specify a concrete default value\"\n                        );\n                    }\n\n                    let desc = DefaultColumnDesc::decode(&**persisted)\n                        .expect(\"failed to decode persisted `DefaultColumnDesc`\");\n\n                    column_catalogs[idx].column_desc.generated_or_default_column =\n                        Some(GeneratedOrDefaultColumn::DefaultColumn(desc));\n                }\n                _ => {}\n            }\n        }\n    }\n    Ok(())\n}\n\n/// Currently we only support Primary key table constraint, so just return pk names if it exists\npub fn bind_table_constraints(table_constraints: &[TableConstraint]) -> Result<Vec<String>> {\n    let mut pk_column_names = vec![];\n\n    for constraint in table_constraints {\n        match constraint {\n            TableConstraint::Unique {","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/handler/create_table.rs#L335-L371","documentation":"`bind_sql_column_constraints` found a persisted `DEFAULT INTERNAL` column default encoded as protobuf bytes, but `DefaultColumnDesc::decode` failed, so the `expect` panics. The stored bytes no longer parse as a valid `DefaultColumnDesc` — a corrupted or format-mismatched catalog entry.","triggerScenarios":"CREATE TABLE/SOURCE (via `bind_create_source_or_table_with_connector`, `gen_create_table_plan_without_source`, `gen_create_table_plan_for_cdc_table`) reading a column whose `generated_or_default_column` holds protobuf bytes that fail protobuf decoding — e.g. bytes written by an incompatible older schema version or manually corrupted meta storage.","commonSituations":"Rolling upgrades where the persisted proto definition changed; restoring state from backups of a different version; meta-store corruption.","solutions":["Recreate the table/source so the default column descriptor is re-encoded with the current format.","Check version compatibility between the meta store data and the running binary; complete any pending upgrade migration.","If a test/fixture wrote raw bytes, generate them via `DefaultColumnDesc` protobuf encode instead of hand-crafting."],"exampleFix":"// before: hand-written bytes that don't decode\nlet persisted: Bytes = Bytes::from_static(b\"garbage\");\n// after: encode a real descriptor\nlet persisted = DefaultColumnDesc { column_id: 1 }.encode_to_vec().into();","handlingStrategy":"type-guard","validationCode":"if let Some(persisted) = default_bytes {\n    match DefaultColumnDesc::decode(&**persisted) {\n        Ok(desc) => { /* proceed */ }\n        Err(e) => return Err(anyhow!(\"corrupt DefaultColumnDesc in catalog: {}\", e)),\n    }\n}","typeGuard":"fn decodable_default(b: &[u8]) -> Option<DefaultColumnDesc> { DefaultColumnDesc::decode(b).ok() }","tryCatchPattern":"match DefaultColumnDesc::decode(&**persisted) {\n    Ok(desc) => apply(desc),\n    Err(e) => log::error!(\"failed to decode DefaultColumnDesc: {e}\"),\n}","preventionTips":["Keep meta-store and binary versions aligned; finish upgrade migrations","Encode fixture bytes via the proto struct, never by hand","Back up and validate catalog state before version rollbacks"],"tags":["rust","protobuf","panic","catalog"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}