{"record":{"id":"0ecdca21b28147ba","repo":"alibaba/nacos","slug":"role-role-admin-is-not-permitted-to-create","errorCode":null,"errorMessage":"role 'ROLE_ADMIN' is not permitted to create!","messagePattern":"role 'ROLE_ADMIN' is not permitted to create!","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceDirectImpl.java","lineNumber":130,"sourceCode":"    \n    @Override\n    public Page<PermissionInfo> getPermissions(String role, int pageNo, int pageSize) {\n        Page<PermissionInfo> pageInfo =\n            permissionPersistService.getPermissions(role, pageNo, pageSize);\n        if (pageInfo == null) {\n            return new Page<>();\n        }\n        return pageInfo;\n    }\n    \n    @Override\n    public void addRole(String role, String username) {\n        if (userDetailsService.getUser(username) == null) {\n            throw new IllegalArgumentException(\"user '\" + username + \"' not found!\");\n        }\n        \n        if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(role)) {\n            throw new IllegalArgumentException(\n                \"role '\" + AuthConstants.GLOBAL_ADMIN_ROLE + \"' is not permitted to create!\");\n        }\n        \n        if (AuthConstants.ANONYMOUS_ROLE.equals(role)) {\n            throw new IllegalArgumentException(\n                \"role '\" + AuthConstants.ANONYMOUS_ROLE + \"' is reserved by the system\");\n        }\n        \n        if (isUserBoundToRole(role, username)) {\n            throw new IllegalArgumentException(\n                \"user '\" + username + \"' already bound to the role '\" + role + \"'!\");\n        }\n        \n        rolePersistService.addRole(role, username);\n        getCachedRoleSet().add(role);\n        invalidateUserRoles(username);\n    }\n    ","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceDirectImpl.java#L112-L148","documentation":"Thrown by addRole when the requested role name equals AuthConstants.GLOBAL_ADMIN_ROLE (\"ROLE_ADMIN\"). Nacos reserves the global administrator role: it can only be granted through the dedicated addAdminRole(username) path, which also tracks single-admin existence, so the generic addRole refuses it. This guard prevents creating duplicate or untracked admin grants.","triggerScenarios":"Calling addRole(\"ROLE_ADMIN\", username) directly; passing a role name read from config/UI that happens to equal ROLE_ADMIN; programmatically seeding roles from a list that includes the admin role.","commonSituations":"Automated bootstrap scripts that blindly insert every role including ROLE_ADMIN; UI forms that let users type the role name freely; migrating role sets from another system without filtering reserved names.","solutions":["To grant admin privileges, use roleService.addAdminRole(username) instead of addRole.","If seeding roles programmatically, skip any role name equal to AuthConstants.GLOBAL_ADMIN_ROLE (\"ROLE_ADMIN\").","Filter the incoming role name list against reserved role names before calling addRole."],"exampleFix":"// before\nroleService.addRole(\"ROLE_ADMIN\", username); // rejected\n\n// after\nroleService.addAdminRole(username);","handlingStrategy":"validation","validationCode":"// Never pass ROLE_ADMIN to addRole; use addAdminRole.\nif (AuthConstants.GLOBAL_ADMIN_ROLE.equals(role)) {\n    roleService.addAdminRole(username);\n} else {\n    roleService.addRole(role, username);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat ROLE_ADMIN as a reserved name in all role-provisioning code.","Route admin grants exclusively through addAdminRole.","Filter reserved role names from imported role catalogs."],"tags":["auth","role","validation","reserved","admin"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}