{"record":{"id":"1bbb7941f9bb4884","repo":"databendlabs/databend","slug":"table-name-is-provided","errorCode":null,"errorMessage":"table name is provided","messagePattern":"table name is provided","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/service/src/interpreters/access/privilege_access.rs","lineNumber":787,"sourceCode":"                                    .await?\n                                    .iter()\n                                    .map(|r| r.name.clone())\n                                    .collect::<Vec<_>>()\n                                    .join(\",\");\n                                Err(ErrorCode::PermissionDenied(format!(\n                                    \"Permission denied: privilege [{:?}] is required on '{}'.'{}'.'{}' for user {} with roles [{}]\",\n                                    UserPrivilegeType::Alter,\n                                    catalog_name,\n                                    db_name,\n                                    table_name,\n                                    &current_user.identity().display(),\n                                    roles_name,\n                                )))\n                            }\n                            Err(err) => Err(err),\n                        }\n                    }\n                    Ok(ObjectId::Database(_)) => unreachable!(\"table name is provided\"),\n                    Err(err) => Err(err.add_message(\"error on validating table index access\")),\n                }\n            }\n            Err(err) => Err(err),\n        }\n    }\n\n    async fn validate_warehouse_ownership(\n        &self,\n        warehouse: String,\n        current_user: String,\n    ) -> Option<Result<()>> {\n        let session = self.ctx.get_current_session();\n        let warehouse_mgr = GlobalInstance::get::<Arc<dyn ResourcesManagement>>();\n\n        // Only check support_forward_warehouse_request privileges\n        if !warehouse_mgr.support_forward_warehouse_request() {\n            return Some(Ok(()));","sourceCodeStart":769,"sourceCodeEnd":805,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/service/src/interpreters/access/privilege_access.rs#L769-L805","documentation":"validate_real_table_alter_access (src/query/service/src/interpreters/access/privilege_access.rs:787) asserts that when validating ALTER access on a table index, the ObjectId resolved from the name is always ObjectId::Table. If it is ObjectId::Database instead, the code panics with unreachable!(\"table name is provided\"). The message is misleading — the panic means a database-level object reached table-level alter validation.","triggerScenarios":"validate_table_index_alter_or_super_access resolves a name to an ObjectId and calls validate_real_table_alter_access; the panic fires when the resolved object is a database rather than a table — e.g. an ALTER statement naming a database (or a name that resolves to a database) is passed through the table-index alter validation path.","commonSituations":"Running ALTER TABLE ... (index-related alter) where the target name is mistyped or refers to a database; hitting name-resolution ambiguity between a database and table of the same name; upgraded clients issuing ALTER on index objects through changed validation paths.","solutions":["Check the statement's target identifier — ensure it names an existing table, not a database, and correct any typo in the table name","Fully qualify the table as <catalog>.<database>.<table> to avoid ambiguity in name resolution","Upgrade to a version where validate_real_table_alter_access returns a PermissionDenied/NotFound error instead of panicking on non-table objects","As a code fix, replace unreachable! with Err(ErrorCode::PermissionDenied(...)) handling the ObjectId::Database case"],"exampleFix":"// before\nOk(ObjectId::Database(_)) => unreachable!(\"table name is provided\"),\n// after\nOk(ObjectId::Database(_)) => Err(ErrorCode::PermissionDenied(\n    \"expected a table for table index alter access, got a database\".to_string(),\n)),","handlingStrategy":"validation","validationCode":"-- verify the target resolves to a table before ALTER\nSHOW TABLES LIKE '<name>' IN <database>;\n-- if empty, the name is a database or typo — do not run ALTER","typeGuard":"match object_id {\n    ObjectId::Table(_) => { /* proceed with alter validation */ }\n    _ => return Err(ErrorCode::PermissionDenied(\"table index alter requires a table object\".into())),\n}","tryCatchPattern":"// fully qualify to remove ambiguity\nif !(name.database.is_some() && name.table.is_some()) {\n    return Err(ErrorCode::BadArguments(\"ALTER target must be <db>.<table>\".into()));\n}","preventionTips":["Always fully qualify ALTER targets as catalog.database.table","Check for database/table name collisions before naming objects","Verify the object kind with SHOW TABLES / SHOW DATABASES before ALTER","Upgrade to builds that return errors instead of panicking on wrong object kinds"],"tags":["rust","unreachable-panic","privilege","alter-table"],"backgroundTag":"internal-invariant-violation","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}