{"record":{"id":"36789b8b5eff663e","repo":"prestodb/presto","slug":"cannot-grant-roles-s-to-s","errorCode":null,"errorMessage":"Cannot grant roles %s to %s ","messagePattern":"Cannot grant roles (.+?) to (.+?) ","errorType":"exception","errorClass":"AccessDeniedException","httpStatus":null,"severity":"error","filePath":"presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java","lineNumber":407,"sourceCode":"\n    public static void denyCallProcedure(String procedureName, String extraInfo)\n    {\n        throw new AccessDeniedException(format(\"Cannot call procedure %s%s\", procedureName, formatExtraInfo(extraInfo)));\n    }\n\n    public static void denyCreateRole(String roleName)\n    {\n        throw new AccessDeniedException(format(\"Cannot create role %s\", roleName));\n    }\n\n    public static void denyDropRole(String roleName)\n    {\n        throw new AccessDeniedException(format(\"Cannot drop role %s\", roleName));\n    }\n\n    public static void denyGrantRoles(Set<String> roles, Set<PrestoPrincipal> grantees)\n    {\n        throw new AccessDeniedException(format(\"Cannot grant roles %s to %s \", roles, grantees));\n    }\n\n    public static void denyRevokeRoles(Set<String> roles, Set<PrestoPrincipal> grantees)\n    {\n        throw new AccessDeniedException(format(\"Cannot revoke roles %s from %s \", roles, grantees));\n    }\n\n    public static void denySetRole(String role)\n    {\n        throw new AccessDeniedException(format(\"Cannot set role %s\", role));\n    }\n\n    public static void denyCreateBranch(String tableName)\n    {\n        denyCreateBranch(tableName, null);\n    }\n\n    public static void denyCreateBranch(String tableName, String extraInfo)","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-spi/src/main/java/com/facebook/presto/spi/security/AccessDeniedException.java#L389-L425","documentation":"Thrown by denyGrantRoles when GRANT ROLE ... TO <principals> is rejected by checkCanGrantRoles. Granting a role requires holding that role with the admin/grant option; the check also inspects the grantees set. Note the message ends with a trailing space by design of the format string.","triggerScenarios":"Executing 'GRANT <role> TO USER/ROLE <grantee>' when the current user lacks the admin option for the given roles or is not permitted to grant to those grantees.","commonSituations":"Team leads granting access without delegated admin option; provisioning scripts granting to principals outside policy; multi-catalog setups where admin option exists in one catalog but not another.","solutions":["Ask a security admin (holder of the role WITH ADMIN OPTION) to perform the GRANT.","Obtain the admin option on the specific role if policy permits delegating it to you.","Check grantee principals — grants to them may be individually blocked.","Confirm you are granting in the correct catalog where your admin option applies."],"exampleFix":"// before (denied: alice lacks admin option)\nGRANT finance_readers TO USER bob; -- run by alice\n// after: run by admin who holds finance_readers WITH ADMIN OPTION","handlingStrategy":"validation","validationCode":"// Verify admin option on each role and grantee policy before granting\nfor (String role : roles) {\n    if (!holdsRoleWithAdminOption(currentUser, role)) {\n        throw new IllegalStateException(\"Missing ADMIN OPTION on role \" + role);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    stmt.execute(grantSql);\n} catch (AccessDeniedException e) {\n    log.warn(\"GRANT {} denied: {} — routing to security admin queue\", roles, e.getMessage());\n}","preventionTips":["Delegate role grants only to principals holding WITH ADMIN OPTION.","Validate grantees (USER vs ROLE) against your IAM before granting.","Scope provisioning scripts per catalog; admin options are catalog-specific."],"tags":["security","roles","access-control","authorization"],"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"}