apache/cassandra · warning
Role ' ' was already granted on
Error message
Role '%s' was already granted %s on %s
What it means
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.
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)
Example fix
// before
session.execute("GRANT SELECT ON ks.tbl TO app_role"); // run on every deploy
// after
Row r = session.execute("LIST ALL PERMISSIONS OF app_role").one();
if (r == null) session.execute("GRANT SELECT ON ks.tbl TO app_role"); Defensive patterns
Strategy: validation
Validate before calling
// before granting, check existing permissions
boolean granted = session.execute("LIST ALL PERMISSIONS OF " + role).all().stream()
.anyMatch(r -> r.getString("permission").equals("SELECT") && r.getString("resource").contains(resource));
if (granted) { /* skip GRANT */ } Prevention
- Make RBAC provisioning scripts idempotent
- Query LIST GRANTS before GRANT
- Track inherited role permissions to avoid redundant grants
When it happens
Trigger: 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.
Common situations: Idempotent setup scripts re-running GRANT statements; automation re-applying grants; granting overlapping permissions to a role that inherits them from another role.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Role ' ' was not granted on
- Aggregation query used on multiple partition keys (IN…
- Aggregation query used without partition key
- Altering permissions on builtin functions is not supported
- <dynamic warning, no literal in source: built by…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/7fd2cdc157fc4f45.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/statements/GrantPermissionsStatement.java:79
}
}
public ResultMessage execute(ClientState state) throws RequestValidationException, RequestExecutionException
{
IAuthorizer authorizer = DatabaseDescriptor.getAuthorizer();
Set<Permission> granted = authorizer.grant(state.getUser(), permissions, resource, grantee);
// We want to warn the client if all the specified permissions have not been granted and the client did
// not specify ALL in the query.
if (!granted.equals(permissions) && !permissions.equals(Permission.ALL))
{
String permissionsStr = permissions.stream()
.filter(permission -> !granted.contains(permission))
.sorted(Permission::compareTo) // guarantee the order for testing
.map(Permission::name)
.collect(Collectors.joining(", "));
ClientWarn.instance.warn(String.format("Role '%s' was already granted %s on %s",
grantee.getRoleName(),
permissionsStr,
resource));
}
return null;
}
@Override
public AuditLogContext getAuditLogContext()
{
String keyspace = resource.hasParent() ? resource.getParent().getName() : resource.getName();
return new AuditLogContext(AuditLogEntryType.GRANT, keyspace, resource.getName());
}
}
View on GitHub (pinned to 88fd0f6a0e)