apache/cassandra · error · UnauthorizedException
Granting permissions on system keyspaces is strictly limited
Error message
Granting permissions on system keyspaces is strictly limited, this operation is not permitted
What it means
Cassandra forbids granting most permissions on (non-virtual) system keyspaces; only a tightly limited subset is allowed. If the granted permission set overlaps Permission.INVALID_FOR_SYSTEM_KEYSPACES on such a resource, UnauthorizedException is thrown during validate().
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/GrantPermissionsStatement.java:58
public class GrantPermissionsStatement extends PermissionsManagementStatement
{
public GrantPermissionsStatement(Set<Permission> permissions, IResource resource, RoleName grantee)
{
super(permissions, resource, grantee);
}
public void validate(ClientState state) throws RequestValidationException
{
super.validate(state);
if (resource instanceof DataResource)
{
DataResource data = (DataResource) resource;
// Only a subset of permissions can be granted on non-virtual system keyspaces
if (!data.isRootLevel()
&& SchemaConstants.isNonVirtualSystemKeyspace(data.getKeyspace())
&& !Collections.disjoint(permissions, Permission.INVALID_FOR_SYSTEM_KEYSPACES))
{
throw new UnauthorizedException("Granting permissions on system keyspaces is strictly limited, " +
"this operation is not permitted");
}
}
}
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)View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Grant on a user-defined keyspace instead of the system keyspace
- Restrict the grant to permissions valid for system keyspaces (those not in INVALID_FOR_SYSTEM_KEYSPACES, e.g. SELECT where permitted)
- Use role-based access on application data rather than opening system keyspaces
Example fix
// before GRANT MODIFY ON KEYSPACE system_auth TO app_role; // UnauthorizedException // after GRANT MODIFY ON KEYSPACE my_app TO app_role;
Defensive patterns
Strategy: validation
Validate before calling
Set<Permission> invalid = Permission.INVALID_FOR_SYSTEM_KEYSPACES;
boolean isSystemKeyspace = SchemaConstants.isNonVirtualSystemKeyspace(ksName);
if (isSystemKeyspace && !Collections.disjoint(requested, invalid)) throw new IllegalArgumentException("grant not permitted on system keyspace " + ksName); Try / catch
try { session.execute(grant); } catch (UnauthorizedException e) { log.error("grant on system keyspace rejected: {}", e.getMessage()); } Prevention
- Never target system/system_schema/system_auth keyspaces in GRANT statements
- Whitelist application keyspaces in provisioning tooling
- Read SchemaConstants.isNonVirtualSystemKeyspace to know the protected list
When it happens
Trigger: GRANT <permission> ON KEYSPACE <system-ish-keyspace> where the keyspace is in SchemaConstants non-virtual system keyspace list (e.g. system, system_schema, system_auth) and the permission is one of the invalid ones (e.g. MODIFY, DROP, ALTER).
Common situations: Attempts to let application users write into system_auth or system_schema; misconfigured provisioning tools that grant blanket permissions including system keyspaces; confusion between virtual keyspaces (allowed differently) and non-virtual ones.
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
- User %s does not have sufficient privileges to perform the r
- Only superusers can drop a role with superuser status
- %s doesn't exist
- You are not authorized to view roles granted to %s
- You are not authorized to view superuser details
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/b466f657b7181748.
Report an issue: GitHub.