alibaba/nacos · warning · IllegalArgumentException
role '__nacos_anonymous_role__' is reserved by the system
Error message
role '__nacos_anonymous_role__' is reserved by the system
What it means
Thrown by addRole when the role name equals AuthConstants.ANONYMOUS_ROLE ("__nacos_anonymous_role__"). That role is an internal system role used for unauthenticated/anonymous access mapping and is provisioned by the system itself; it cannot be created through the public role API. The check protects the internal anonymous permission set from being overwritten.
Source
Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceDirectImpl.java:135
if (pageInfo == null) {
return new Page<>();
}
return pageInfo;
}
@Override
public void addRole(String role, String username) {
if (userDetailsService.getUser(username) == null) {
throw new IllegalArgumentException("user '" + username + "' not found!");
}
if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(role)) {
throw new IllegalArgumentException(
"role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' is not permitted to create!");
}
if (AuthConstants.ANONYMOUS_ROLE.equals(role)) {
throw new IllegalArgumentException(
"role '" + AuthConstants.ANONYMOUS_ROLE + "' is reserved by the system");
}
if (isUserBoundToRole(role, username)) {
throw new IllegalArgumentException(
"user '" + username + "' already bound to the role '" + role + "'!");
}
rolePersistService.addRole(role, username);
getCachedRoleSet().add(role);
invalidateUserRoles(username);
}
@Override
public void addAdminRole(String username) {
if (userDetailsService.getUser(username) == null) {
throw new IllegalArgumentException("user '" + username + "' not found!");
}View on GitHub (pinned to 9b989acdf1)
Solutions
- Remove __nacos_anonymous_role__ (and ROLE_ADMIN) from any role list you feed to addRole.
- Manage anonymous access through the system's authorization config, not by recreating the role.
- Add a guard that rejects role names matching AuthConstants.ANONYMOUS_ROLE before calling the API.
Example fix
// before
for (String r : roles) roleService.addRole(r, username); // blows up on anonymous
// after
Set<String> reserved = Set.of("ROLE_ADMIN", "__nacos_anonymous_role__");
roles.stream().filter(r -> !reserved.contains(r))
.forEach(r -> roleService.addRole(r, username)); Defensive patterns
Strategy: validation
Validate before calling
Set<String> reserved = Set.of(AuthConstants.GLOBAL_ADMIN_ROLE, AuthConstants.ANONYMOUS_ROLE);
if (reserved.contains(role)) {
throw new IllegalArgumentException("Refusing to create reserved system role: " + role);
}
roleService.addRole(role, username); Prevention
- Maintain a reserved-role blocklist and check it before addRole.
- Do not attempt to recreate system-managed roles.
- Manage anonymous/admin behavior through config, not role creation.
When it happens
Trigger: Calling addRole("__nacos_anonymous_role__", username); importing an external role catalog that includes the anonymous role; a misconfigured role-sync job feeding literal reserved names.
Common situations: Bulk role import without a reserved-name blocklist; tools or Helm charts that attempt to recreate every default role; misunderstanding that the anonymous role is system-managed.
Related errors
- role 'ROLE_ADMIN' is not permitted to create!
- role '__nacos_anonymous_role__' is reserved by the system
- user '{username}' not found!
- role {role} not found!
- role 'ROLE_ADMIN' is not permitted to create!
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/cbe75d7657084137.
Report an issue: GitHub.