prestodb/presto · error · AccessDeniedException
Cannot drop a branch from table %s%s
Error message
Cannot drop a branch from table %s%s
What it means
denyDropBranch throws AccessDeniedException when the access control layer denies dropping a branch from the given table. Presto checks DROP BRANCH authorization before executing the statement; connectors call denyDropBranch(tableName, extraInfo) to raise it.
Source
Thrown at presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java:447
public static void denyCreateTag(String tableName)
{
denyCreateTag(tableName, null);
}
public static void denyCreateTag(String tableName, String extraInfo)
{
throw new AccessDeniedException(format("Cannot create tag on table %s%s", tableName, formatExtraInfo(extraInfo)));
}
public static void denyDropBranch(String tableName)
{
denyDropBranch(tableName, null);
}
public static void denyDropBranch(String tableName, String extraInfo)
{
throw new AccessDeniedException(format("Cannot drop a branch from table %s%s", tableName, formatExtraInfo(extraInfo)));
}
public static void denyDropTag(String tableName)
{
denyDropTag(tableName, null);
}
public static void denyDropTag(String tableName, String extraInfo)
{
throw new AccessDeniedException(format("Cannot drop a tag from table %s%s", tableName, formatExtraInfo(extraInfo)));
}
public static void denyDropConstraint(String tableName)
{
denyDropConstraint(tableName, null);
}
public static void denyDropConstraint(String tableName, String extraInfo)View on GitHub (pinned to 55bb57d202)
Solutions
- Grant DROP BRANCH (or table ownership/admin) to the user/group in the access-control policy
- Verify the user is matching the intended principal in the policy (impersonation, group membership, Kerberos/LDAP mapping)
- Use a service account with the required privileges for automated branch lifecycle jobs
- If the branch should not be droppable, that is expected behavior — switch to expiring snapshots instead
Example fix
// before
{"catalog": "iceberg", "group": "analysts", "privileges": ["SELECT"]}
// after
{"catalog": "iceberg", "group": "analysts", "privileges": ["SELECT", "DROP BRANCH"]} Defensive patterns
Strategy: try-catch
Validate before calling
// check DROP BRANCH privilege before destructive branch cleanup
if (!grants(user, catalog, table).contains("DROP BRANCH")) {
throw new IllegalStateException("DROP BRANCH not granted");
} Type guard
boolean canDropBranch(String user, String table, Map<String, Set<String>> grants) {
return grants.getOrDefault(user, Set.of()).stream().anyMatch(g -> g.startsWith(table) && g.endsWith("DROP BRANCH"));
} Try / catch
try {
conn.execute("ALTER TABLE t DROP BRANCH b");
} catch (AccessDeniedException e) {
LOG.warn("DROP BRANCH denied: %s", e.getMessage());
// rethrow or fall back to requesting elevated credentials
throw e;
} Prevention
- Run branch lifecycle automation with dedicated service accounts holding the needed privileges
- Verify principal identity mapping (impersonation/Kerberos) in policies
- Keep destructive privileges explicit rather than wildcarded
- Audit dropped-denied events to find policy gaps
When it happens
Trigger: A connector calls checkCanDropBranch; the policy rejects and calls denyDropBranch, producing 'Cannot drop a branch from table <table><extraInfo>'.
Common situations: Users cleaning up old branches on tables they can read but not administer; dropping branches created by other users/roles; overly strict policy plugins that never grant destructive operations.
Related errors
- Cannot create branch on table %s%s
- Cannot set role %s
- Cannot create tag on table %s%s
- Cannot drop a tag from table %s%s
- Cannot drop a constraint from table %s%s
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/ebecc73a89994d4a.
Report an issue: GitHub.