apache/cassandra · error · UnauthorizedException

Only superusers can create a role with superuser status

Error message

Only superusers can create a role with superuser status

What it means

CreateRoleStatement.authorize enforces that only superusers may set the SUPERUSER option when creating a role. If a non-superuser authenticated user issues CREATE ROLE ... WITH SUPERUSER = true, Cassandra throws UnauthorizedException to prevent privilege escalation.

Solutions

  1. Run the CREATE ROLE statement as a superuser account.
  2. Remove the SUPERUSER = true option and have a superuser alter the role afterward.
  3. Grant the necessary permissions properly: create the role without SUPERUSER, then have a superuser execute ALTER ROLE foo WITH SUPERUSER = true.

Example fix

// before (as non-superuser)
CREATE ROLE admin WITH SUPERUSER = true AND LOGIN = true;
// after (as superuser, or two-step)
CREATE ROLE admin WITH LOGIN = true;
-- then, connected as a superuser:
ALTER ROLE admin WITH SUPERUSER = true;
Defensive patterns

Strategy: validation

Validate before calling

// client-side pre-check
boolean wantsSuperuser = createCql.contains("SUPERUSER = true");
if (wantsSuperuser && !currentUserIsSuperuser(session)) throw new IllegalStateException("requires superuser connection");

Try / catch

try { session.execute(createRoleCql); } catch (UnauthorizedException e) { if (e.getMessage().contains("Only superusers can create a role with superuser status")) { /* retry via superuser connection or two-step create+alter */ } else throw e; }

Prevention

When it happens

Trigger: A logged-in non-superuser executes CREATE ROLE foo WITH SUPERUSER = true (or LOGIN/SUPERUSER options implying superuser status).

Common situations: Operators granting role-creation rights via a custom role manager but forgetting Cassandra still reserves SUPERUSER creation for superusers; automation running with a provisioned non-super account attempting to bootstrap admin roles; post-upgrade from systems without this check.

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/a5d3a160a204714c. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/CreateRoleStatement.java:73

    {
        if (options.isGeneratedName())
            this.role = RoleResource.GENERATED_ROLE;
        else
            this.role = RoleResource.role(name.getName());

        this.opts = options;
        this.dcPermissions = dcPermissions;
        this.cidrPermissions = cidrPermissions;
        this.ifNotExists = ifNotExists;
    }

    public void authorize(ClientState state) throws UnauthorizedException
    {
        super.checkPermission(state, Permission.CREATE, RoleResource.root());
        if (opts.getSuperuser().isPresent())
        {
            if (opts.getSuperuser().get() && !state.getUser().isSuper())
                throw new UnauthorizedException("Only superusers can create a role with superuser status");
        }
    }

    public void validate(ClientState state) throws RequestValidationException
    {
        opts.validate();
        if (role.getRoleName().isEmpty())
            throw new InvalidRequestException("Role name can't be an empty string");

        if (dcPermissions != null)
        {
            dcPermissions.validate();
        }

        if (cidrPermissions != null)
        {
            cidrPermissions.validate();
        }

View on GitHub (pinned to 88fd0f6a0e)