{"record":{"id":"0e16efff68491a42","repo":"apache/cassandra","slug":"alter-role-user-can-t-be-empty","errorCode":null,"errorMessage":"ALTER [ROLE|USER] can't be empty","messagePattern":"ALTER \\[ROLE\\|USER\\] can't be empty","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/AlterRoleStatement.java","lineNumber":76,"sourceCode":"        this(name, opts, null, null, false);\n    }\n\n    public AlterRoleStatement(RoleName name, RoleOptions opts, DCPermissions dcPermissions,\n                              CIDRPermissions cidrPermissions, boolean ifExists)\n    {\n        this.role = RoleResource.role(name.getName());\n        this.opts = opts;\n        this.dcPermissions = dcPermissions;\n        this.cidrPermissions = cidrPermissions;\n        this.ifExists = ifExists;\n    }\n\n    public void validate(ClientState state) throws RequestValidationException\n    {\n        opts.validate();\n\n        if (opts.isEmpty() && dcPermissions == null && cidrPermissions == null)\n            throw new InvalidRequestException(\"ALTER [ROLE|USER] can't be empty\");\n\n        if (dcPermissions != null)\n        {\n            dcPermissions.validate();\n        }\n\n        if (cidrPermissions != null)\n        {\n            // Ensure input CIDR group names are valid, i.e, existing in CIDR groups mapping table\n            cidrPermissions.validate();\n        }\n\n        // validate login here before authorize, to avoid leaking user existence to anonymous users.\n        state.ensureNotAnonymous();\n        if (!DatabaseDescriptor.getRoleManager().isExistingRole(role))\n        {\n            checkTrue(ifExists, \"Role %s doesn't exist\", role.getRoleName());\n        }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/AlterRoleStatement.java#L58-L94","documentation":"AlterRoleStatement.validate rejects an ALTER ROLE/USER statement that specifies nothing to change: no role options, no DC permissions change, and no CIDR permissions change. Such a statement is a no-op and is treated as invalid input.","triggerScenarios":"ALTER ROLE some_role; or ALTER USER alice; with no WITH option clause and no dcPermissions/cidrPermissions clause, after opts.validate() passes.","commonSituations":"Programmatically generated ALTER statements where all option fields were empty; partial template rendering that dropped the options; fat-fingered statements with only the role name.","solutions":["Add at least one option, e.g. WITH PASSWORD = '...', WITH LOGIN = true, or SUPERUSER = false","Add a DC ACCESS or CIDR permissions clause if that is the intended change","Remove the statement entirely if no change was intended"],"exampleFix":"// before\nALTER ROLE app_role;\n// after\nALTER ROLE app_role WITH LOGIN = true;","handlingStrategy":"validation","validationCode":"// ensure the ALTER has at least one change before executing\nboolean hasChange = !options.isEmpty() || dcPermissions != null || cidrPermissions != null;\nif (!hasChange) throw new IllegalArgumentException(\"ALTER ROLE needs at least one option, DC permission, or CIDR permission\");","typeGuard":null,"tryCatchPattern":"try { session.execute(alterRoleCql); } catch (InvalidRequestException e) { if (e.getMessage().contains(\"can't be empty\")) { /* skip no-op or add options */ } else throw e; }","preventionTips":["Build ALTER statements programmatically only when at least one option is set","Skip generating the statement entirely when the change set is empty","Lint generated CQL for bare 'ALTER ROLE x;' statements"],"tags":["cql","roles","empty-argument"],"backgroundTag":"empty-required-field","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}