databendlabs/databend · error
internal error: entered unreachable code
Error message
internal error: entered unreachable code
What it means
access_system_history (src/query/service/src/interpreters/access/privilege_access.rs:319) matches on the (catalog_name, db_name, stage_name) tuple and only handles two shapes: (Some, Some, None) for the sensitive history database and (None, None, Some) for the sensitive history stage. Any other combination — including all-None or mixed Some/Some/Some — falls into `_ => unreachable!()`, panicking the query node with 'internal error: entered unreachable code'.
Solutions
- Identify which statement triggered validation with the unhandled identifier combination (check query log) and rework the statement to reference either a history database table or the history stage, not both/neither
- Upgrade to a Databend version where access_system_history returns PermissionDenied for unhandled shapes instead of panicking
- As a code fix, replace the `_ => unreachable!()` arm with `Err(ErrorCode::PermissionDenied(...))` or `Ok(())` so unexpected shapes degrade gracefully
- File a bug with the exact SQL statement and Databend version
Example fix
// before
_ => unreachable!(),
// after
_ => Err(ErrorCode::PermissionDenied(
"Permission Denied: unhandled object shape for sensitive system history resource".to_string(),
)), Defensive patterns
Strategy: validation
Validate before calling
-- only reference history objects in the supported shapes: -- a table under <catalog>.system_history, or the history stage alone SELECT * FROM default.system_history.log_tbl; -- avoid mixed references like a db+stage in one grant
Type guard
let shape = (catalog_name.is_some(), db_name.is_some(), stage_name.is_some());
if !matches!(shape, (true, true, false) | (false, false, true)) {
// route away from access_system_history
} Try / catch
// callers (validate_*_access) should pre-check identifier arity
if (catalog.is_some() || db.is_some()) && stage.is_some() {
return Err(ErrorCode::BadArguments("cannot mix database and stage identifiers".into()));
} Prevention
- Grant privileges on history tables and stages with fully qualified, single-object references
- Do not mix stage and database identifiers in one privilege operation
- Keep account_admin role for sensitive history stage operations
- Upgrade before using new system-history features on older nodes
When it happens
Trigger: Any privilege validation call that reaches access_system_history with an argument shape outside the two handled patterns: e.g. validating access with both db_name and stage_name set, with catalog only (db_name None), or with all three None. Reached through validate_db_access, validate_table_access, validate_table_index_access, validate_drop_table_index_access, or validate_stage_access.
Common situations: A user queries or mutates a history/log table or stage through a code path that passes an unexpected combination of object identifiers (e.g. a fully-qualified name including both database and stage, or a validation hook invoked with None identifiers); common after upgrades where new object kinds route through the shared validation entry points.
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
- table name is provided
- logic error: expected CreateTable plan
- internal error: entered unreachable code
- Input plan must be Query, but it's
- Input plan must be Query, but it's
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/48ba7faf4af263d9.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/interpreters/access/privilege_access.rs:319
if current_role.name == BUILTIN_ROLE_ACCOUNT_ADMIN {
Ok(())
} else {
Err(ErrorCode::PermissionDenied(format!(
"Permission Denied: Operation '{:?}' on stage {sensitive_system_stage} is not allowed",
privilege
)))
}
} else {
Err(ErrorCode::PermissionDenied(format!(
"Permission Denied: Operation '{:?}' on stage {sensitive_system_stage} is not allowed",
privilege
)))
}
} else {
Ok(())
};
}
_ => unreachable!(),
}
Ok(())
}
async fn get_role_names_and_ownerships(
&self,
tenant: &Tenant,
) -> Result<(Vec<String>, Vec<SeqV<OwnershipInfo>>)> {
let roles = self.ctx.get_all_effective_roles().await?;
let roles_name = roles
.iter()
.map(|role| role.name.to_string())
.collect::<Vec<_>>();
if roles_name
.iter()
.any(|role_name| role_name == BUILTIN_ROLE_ACCOUNT_ADMIN)View on GitHub (pinned to 288d84d76e)