prestodb/presto · error · AccessDeniedException

Cannot revoke roles %s from %s

Error message

Cannot revoke roles %s from %s 

What it means

Thrown by denyRevokeRoles when REVOKE ROLE ... FROM <principals> is rejected by checkCanRevokeRoles. Revoking requires the admin option on the roles involved, and the check validates each grantee. Message ends with a trailing space per its format string.

Source

Thrown at presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java:412

    public static void denyCreateRole(String roleName)
    {
        throw new AccessDeniedException(format("Cannot create role %s", roleName));
    }

    public static void denyDropRole(String roleName)
    {
        throw new AccessDeniedException(format("Cannot drop role %s", roleName));
    }

    public static void denyGrantRoles(Set<String> roles, Set<PrestoPrincipal> grantees)
    {
        throw new AccessDeniedException(format("Cannot grant roles %s to %s ", roles, grantees));
    }

    public static void denyRevokeRoles(Set<String> roles, Set<PrestoPrincipal> grantees)
    {
        throw new AccessDeniedException(format("Cannot revoke roles %s from %s ", roles, grantees));
    }

    public static void denySetRole(String role)
    {
        throw new AccessDeniedException(format("Cannot set role %s", role));
    }

    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)

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Have a security admin with the role's ADMIN OPTION execute the REVOKE.
  2. Obtain the admin option on the role if your governance process allows.
  3. Verify the grantee names (USER vs ROLE) — wrong principal kind can hit denial paths.
  4. Confirm the role actually has grants in the targeted catalog before revoking.

Example fix

// before (denied)
REVOKE finance_readers FROM USER bob; -- run by non-admin
// after: executed by an admin holding finance_readers WITH ADMIN OPTION
Defensive patterns

Strategy: validation

Validate before calling

for (String role : roles) {
    if (!holdsRoleWithAdminOption(currentUser, role)) {
        throw new IllegalStateException("REVOKE requires ADMIN OPTION on role " + role);
    }
}

Try / catch

try {
    stmt.execute(revokeSql);
} catch (AccessDeniedException e) {
    log.warn("REVOKE {} denied: {} — escalate to security admin", roles, e.getMessage());
}

Prevention

When it happens

Trigger: Executing 'REVOKE <role> FROM USER/ROLE <grantee>' when the current user lacks the admin option for those roles or cannot revoke from those grantees.

Common situations: Offboarding scripts removing access run by non-admin service accounts; revoking a role in a catalog where you hold admin in a different catalog only; revoking grants made by another admin without admin option.

Related errors


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