{"record":{"id":"9314ec507a7dbd70","repo":"risingwavelabs/risingwave","slug":"should-already-checked-index-referencing-column-st","errorCode":null,"errorMessage":"should already checked index referencing column still exists","messagePattern":"should already checked index referencing column still exists","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/meta/src/controller/rename.rs","lineNumber":465,"sourceCode":"/// Rewrite the expression in index item after there's a schema change on the primary table.\n// TODO: move this out of `rename.rs`, this has nothing to do with renaming.\npub struct IndexItemRewriter {\n    pub original_columns: Vec<PbColumnDesc>,\n    pub new_columns: Vec<PbColumnDesc>,\n}\n\nimpl IndexItemRewriter {\n    pub fn rewrite_expr(&self, expr: &mut ExprNode) {\n        let rex_node = expr.rex_node.as_mut().unwrap();\n        match rex_node {\n            RexNode::InputRef(idx) => {\n                let old_idx = *idx as usize;\n                let original_column = &self.original_columns[old_idx];\n                let (new_idx, new_column) = self\n                    .new_columns\n                    .iter()\n                    .find_position(|c| c.column_id == original_column.column_id)\n                    .expect(\"should already checked index referencing column still exists\");\n                *idx = new_idx as u32;\n\n                // If there's a type change, we need to wrap it with an internal `CompositeCast` to\n                // maintain the correct return type. It cannot execute and will be eliminated in\n                // the frontend when rebuilding the index items.\n                if new_column.column_type != original_column.column_type {\n                    let old_type = original_column.column_type.clone().unwrap();\n                    let new_type = new_column.column_type.clone().unwrap();\n\n                    assert_eq!(&old_type, expr.return_type.as_ref().unwrap());\n                    expr.return_type = Some(new_type); // update return type of `InputRef`\n\n                    let new_expr_node = ExprNode {\n                        function_type: expr_node::Type::CompositeCast as _,\n                        return_type: Some(old_type),\n                        rex_node: RexNode::FuncCall(FunctionCall {\n                            children: vec![expr.clone()],\n                        })","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/controller/rename.rs#L447-L483","documentation":"When rewriting an index after ALTER TABLE ADD/DROP COLUMN, rewrite_expr maps an old column index to the new column list by matching column_id. The expect asserts a prior check already verified the referenced column still exists; panicking means an index references a column that was dropped or the column-id mapping is inconsistent.","triggerScenarios":"Renaming/rewriting a table whose index items reference a column absent from new_columns — i.e. the earlier 'index references dropped column' validation was skipped, bypassed, or the column-id bookkeeping is wrong (e.g. after concurrent ALTERs).","commonSituations":"Dropping a column that an index depends on without the pre-check firing, schema corruption after failed ALTER, concurrent DDL races.","solutions":["Verify the index does not reference the column being dropped before issuing ALTER TABLE DROP COLUMN (the check that normally prevents this).","Re-create the index without the dropped column, or drop the index first.","If column ids are inconsistent in the meta store, restore from backup / rebuild the table and index."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before DROP COLUMN, check no index item references it\nif indexes_reference_column(table_id, column_id) {\n    bail!(\"cannot drop column referenced by an index\");\n}","typeGuard":null,"tryCatchPattern":"std::panic::catch_unwind(|| rewrite_expr(expr, &ctx))","preventionTips":["Always rely on the pre-check that a referenced column still exists","Drop dependent indexes before dropping their columns","Avoid concurrent ALTER TABLE operations on the same table","Verify column-id mapping consistency after partial ALTER failures"],"tags":["panic","index","alter-table","invariant"],"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-23T08:17:48.524Z"}