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

  1. Grant the user/group CREATE TAG privilege in the active access-control configuration
  2. Check the policy file/plugin actually loaded (look for config parse warnings in server logs) — a silently unloaded policy may deny everything
  3. Confirm the tag DDL targets the correct catalog/table the policy grants cover
  4. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/be63e65d4ccbd30c. Report an issue: GitHub.