{"record":{"id":"ebecc73a89994d4a","repo":"prestodb/presto","slug":"cannot-drop-a-branch-from-table-s-s","errorCode":null,"errorMessage":"Cannot drop a branch from table %s%s","messagePattern":"Cannot drop a branch from table (.+?)(.+?)","errorType":"exception","errorClass":"AccessDeniedException","httpStatus":null,"severity":"error","filePath":"presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java","lineNumber":447,"sourceCode":"\n    public static void denyCreateTag(String tableName)\n    {\n        denyCreateTag(tableName, null);\n    }\n\n    public static void denyCreateTag(String tableName, String extraInfo)\n    {\n        throw new AccessDeniedException(format(\"Cannot create tag on table %s%s\", tableName, formatExtraInfo(extraInfo)));\n    }\n\n    public static void denyDropBranch(String tableName)\n    {\n        denyDropBranch(tableName, null);\n    }\n\n    public static void denyDropBranch(String tableName, String extraInfo)\n    {\n        throw new AccessDeniedException(format(\"Cannot drop a branch from table %s%s\", tableName, formatExtraInfo(extraInfo)));\n    }\n\n    public static void denyDropTag(String tableName)\n    {\n        denyDropTag(tableName, null);\n    }\n\n    public static void denyDropTag(String tableName, String extraInfo)\n    {\n        throw new AccessDeniedException(format(\"Cannot drop a tag from table %s%s\", tableName, formatExtraInfo(extraInfo)));\n    }\n\n    public static void denyDropConstraint(String tableName)\n    {\n        denyDropConstraint(tableName, null);\n    }\n\n    public static void denyDropConstraint(String tableName, String extraInfo)","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java#L429-L465","documentation":"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.","triggerScenarios":"A connector calls checkCanDropBranch; the policy rejects and calls denyDropBranch, producing 'Cannot drop a branch from table <table><extraInfo>'.","commonSituations":"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.","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"],"exampleFix":"// before\n{\"catalog\": \"iceberg\", \"group\": \"analysts\", \"privileges\": [\"SELECT\"]}\n// after\n{\"catalog\": \"iceberg\", \"group\": \"analysts\", \"privileges\": [\"SELECT\", \"DROP BRANCH\"]}","handlingStrategy":"try-catch","validationCode":"// check DROP BRANCH privilege before destructive branch cleanup\nif (!grants(user, catalog, table).contains(\"DROP BRANCH\")) {\n    throw new IllegalStateException(\"DROP BRANCH not granted\");\n}","typeGuard":"boolean canDropBranch(String user, String table, Map<String, Set<String>> grants) {\n    return grants.getOrDefault(user, Set.of()).stream().anyMatch(g -> g.startsWith(table) && g.endsWith(\"DROP BRANCH\"));\n}","tryCatchPattern":"try {\n    conn.execute(\"ALTER TABLE t DROP BRANCH b\");\n} catch (AccessDeniedException e) {\n    LOG.warn(\"DROP BRANCH denied: %s\", e.getMessage());\n    // rethrow or fall back to requesting elevated credentials\n    throw e;\n}","preventionTips":["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"],"tags":["presto","security","access-denied","branching"],"backgroundTag":"access-denied-authorization","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}