databendlabs/databend · error

table name is provided

Error message

table name is provided

What it means

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.

Solutions

  1. Check the statement's target identifier — ensure it names an existing table, not a database, and correct any typo in the table name
  2. Fully qualify the table as <catalog>.<database>.<table> to avoid ambiguity in name resolution
  3. Upgrade to a version where validate_real_table_alter_access returns a PermissionDenied/NotFound error instead of panicking on non-table objects
  4. As a code fix, replace unreachable! with Err(ErrorCode::PermissionDenied(...)) handling the ObjectId::Database case

Example fix

// before
Ok(ObjectId::Database(_)) => unreachable!("table name is provided"),
// after
Ok(ObjectId::Database(_)) => Err(ErrorCode::PermissionDenied(
    "expected a table for table index alter access, got a database".to_string(),
)),
Defensive patterns

Strategy: validation

Validate before calling

-- verify the target resolves to a table before ALTER
SHOW TABLES LIKE '<name>' IN <database>;
-- if empty, the name is a database or typo — do not run ALTER

Type guard

match object_id {
    ObjectId::Table(_) => { /* proceed with alter validation */ }
    _ => return Err(ErrorCode::PermissionDenied("table index alter requires a table object".into())),
}

Try / catch

// fully qualify to remove ambiguity
if !(name.database.is_some() && name.table.is_some()) {
    return Err(ErrorCode::BadArguments("ALTER target must be <db>.<table>".into()));
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/1bbb7941f9bb4884. Report an issue: GitHub.

Appendix: source

Thrown at src/query/service/src/interpreters/access/privilege_access.rs:787

                                    .await?
                                    .iter()
                                    .map(|r| r.name.clone())
                                    .collect::<Vec<_>>()
                                    .join(",");
                                Err(ErrorCode::PermissionDenied(format!(
                                    "Permission denied: privilege [{:?}] is required on '{}'.'{}'.'{}' for user {} with roles [{}]",
                                    UserPrivilegeType::Alter,
                                    catalog_name,
                                    db_name,
                                    table_name,
                                    &current_user.identity().display(),
                                    roles_name,
                                )))
                            }
                            Err(err) => Err(err),
                        }
                    }
                    Ok(ObjectId::Database(_)) => unreachable!("table name is provided"),
                    Err(err) => Err(err.add_message("error on validating table index access")),
                }
            }
            Err(err) => Err(err),
        }
    }

    async fn validate_warehouse_ownership(
        &self,
        warehouse: String,
        current_user: String,
    ) -> Option<Result<()>> {
        let session = self.ctx.get_current_session();
        let warehouse_mgr = GlobalInstance::get::<Arc<dyn ResourcesManagement>>();

        // Only check support_forward_warehouse_request privileges
        if !warehouse_mgr.support_forward_warehouse_request() {
            return Some(Ok(()));

View on GitHub (pinned to 288d84d76e)