prestodb/presto · error · AccessDeniedException
Cannot create tag on table %s%s
Error message
Cannot create tag on table %s%s
What it means
denyCreateTag throws AccessDeniedException when the access control layer denies creating a tag (a named immutable snapshot reference, e.g. in Iceberg-style table versioning) on the given table. The optional extraInfo parameter appends additional context to the message.
Source
Thrown at presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java:437
public static void denyCreateBranch(String tableName)
{
denyCreateBranch(tableName, null);
}
public static void denyCreateBranch(String tableName, String extraInfo)
{
throw new AccessDeniedException(format("Cannot create branch on table %s%s", tableName, formatExtraInfo(extraInfo)));
}
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)View on GitHub (pinned to 55bb57d202)
Solutions
- Grant the user/group CREATE TAG privilege in the active access-control configuration
- Check the policy file/plugin actually loaded (look for config parse warnings in server logs) — a silently unloaded policy may deny everything
- Confirm the tag DDL targets the correct catalog/table the policy grants cover
- If tags should be self-service, add a rule scoped to the relevant schema rather than globally
Example fix
// before
GRANT-less policy: {"user": "bob", "allow": false}
// after
{"user": "bob", "privileges": ["CREATE TAG"], "allow": true} Defensive patterns
Strategy: try-catch
Validate before calling
// confirm the user holds CREATE TAG before issuing the statement
boolean canCreateTag = policyClient.hasPrivilege(user, catalog, table, "CREATE TAG");
if (!canCreateTag) { throw new IllegalStateException("Missing CREATE TAG privilege"); } Type guard
boolean isPrivileged(java.security.Principal p, Map<String, Set<String>> grants, String table) {
return p != null && grants.getOrDefault(p.getName(), Set.of()).stream().anyMatch(g -> g.contains(table));
} Try / catch
try {
conn.execute("ALTER TABLE t CREATE TAG release_1");
} catch (AccessDeniedException e) {
LOG.warn("CREATE TAG denied: %s", e.getMessage());
throw e;
} Prevention
- Include tag operations in policy privilege enumerations
- Confirm policy file/plugin loads cleanly at server startup
- Use fully qualified table names in grants
- Add integration tests that exercise tag DDL with a real principal
When it happens
Trigger: A connector calls checkCanCreateTag; its policy rejects the operation and calls denyCreateTag(tableName, extraInfo), yielding 'Cannot create tag on table <table><extraInfo>'.
Common situations: Users executing CREATE TAG statements on tables governed by restrictive access control; missing table-level privilege grants after migrating catalogs; policy plugins that enumerate allowed operations without including TAG operations.
Related errors
- Cannot drop a tag from table %s%s
- Cannot set role %s
- Cannot create branch on table %s%s
- Cannot drop a branch 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/be63e65d4ccbd30c.
Report an issue: GitHub.