{"record":{"id":"7fd2cdc157fc4f45","repo":"apache/cassandra","slug":"role-s-was-already-granted-s-on-s","errorCode":null,"errorMessage":"Role '%s' was already granted %s on %s","messagePattern":"Role '(.+?)' was already granted (.+?) on (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/cql3/statements/GrantPermissionsStatement.java","lineNumber":79,"sourceCode":"        }\n    }\n\n    public ResultMessage execute(ClientState state) throws RequestValidationException, RequestExecutionException\n    {\n        IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();\n        Set<Permission> granted = authorizer.grant(state.getUser(), permissions, resource, grantee);\n\n        // We want to warn the client if all the specified permissions have not been granted and the client did\n        // not specify ALL in the query.\n        if (!granted.equals(permissions) && !permissions.equals(Permission.ALL))\n        {\n            String permissionsStr = permissions.stream()\n                                               .filter(permission -> !granted.contains(permission))\n                                               .sorted(Permission::compareTo) // guarantee the order for testing\n                                               .map(Permission::name)\n                                               .collect(Collectors.joining(\", \"));\n\n            ClientWarn.instance.warn(String.format(\"Role '%s' was already granted %s on %s\",\n                                                   grantee.getRoleName(),\n                                                   permissionsStr,\n                                                   resource));\n        }\n\n        return null;\n    }\n\n    @Override\n    public AuditLogContext getAuditLogContext()\n    {\n        String keyspace = resource.hasParent() ? resource.getParent().getName() : resource.getName();\n        return new AuditLogContext(AuditLogEntryType.GRANT, keyspace, resource.getName());\n    }\n\n}\n","sourceCodeStart":61,"sourceCodeEnd":96,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/GrantPermissionsStatement.java#L61-L96","documentation":"GRANT role/permissions on a resource where the grantee already holds (a superset of) the requested permissions produces this client warning instead of an error. The statement filters out already-granted permissions and warns about the redundant remainder.","triggerScenarios":"Running `GRANT permission ON resource TO role` where the role already has the permission, directly or via inheritance; GrantPermissionsStatement.execute collects not-granted permissions and warns when the intersection is non-empty.","commonSituations":"Idempotent setup scripts re-running GRANT statements; automation re-applying grants; granting overlapping permissions to a role that inherits them from another role.","solutions":["Check existing grants with LIST ALL PERMISSIONS OF role_name before granting","Make provisioning scripts idempotent (issue GRANT only when LIST GRANTS shows it missing)","If redundant grants are expected, downgrade the warning handling on the client (setWarnings callback)"],"exampleFix":"// before\nsession.execute(\"GRANT SELECT ON ks.tbl TO app_role\"); // run on every deploy\n// after\nRow r = session.execute(\"LIST ALL PERMISSIONS OF app_role\").one();\nif (r == null) session.execute(\"GRANT SELECT ON ks.tbl TO app_role\");","handlingStrategy":"validation","validationCode":"// before granting, check existing permissions\nboolean granted = session.execute(\"LIST ALL PERMISSIONS OF \" + role).all().stream()\n    .anyMatch(r -> r.getString(\"permission\").equals(\"SELECT\") && r.getString(\"resource\").contains(resource));\nif (granted) { /* skip GRANT */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make RBAC provisioning scripts idempotent","Query LIST GRANTS before GRANT","Track inherited role permissions to avoid redundant grants"],"tags":["cassandra","permissions","rbac","client-warning"],"backgroundTag":"permission-denied","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}