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 the remote addRole when the role name equals ANONYMOUS_ROLE ("__nacos_anonymous_role__"). Mirrors the direct impl guard: the anonymous role is system-managed and cannot be created through the public API. The check is local on the console node, so no remote request is issued.
Source
Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceRemoteImpl.java:174
throw new NacosRuntimeException(NacosException.SERVER_ERROR,
unpectedException.getMessage());
}
}
@Override
public List<RoleInfo> getAllRoles() {
return getRoles(StringUtils.EMPTY, StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE)
.getPageItems();
}
@Override
public void addRole(String role, String username) {
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");
}
Map<String, String> body = Map.of("role", role, "username", username);
try {
HttpRestResult<String> httpResult = nacosRestTemplate.postForm(
buildRemoteRoleUrlPath(AuthConstants.ROLE_PATH),
RemoteServerUtil.buildServerRemoteHeader(), body, String.class);
RemoteServerUtil.singleCheckResult(httpResult);
getCachedRoleSet().add(role);
invalidateUserRoles(username);
} catch (NacosException e) {
throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
} catch (Exception unpectedException) {
throw new NacosRuntimeException(NacosException.SERVER_ERROR,
unpectedException.getMessage());
}
}
View on GitHub (pinned to 9b989acdf1)
Solutions
- Exclude __nacos_anonymous_role__ from role lists fed to addRole.
- Manage anonymous access via authorization configuration, not role creation.
- Add a reserved-name blocklist in your provisioning code.
Example fix
// before
roles.forEach(r -> roleService.addRole(r, username)); // fails 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)) {
roleService.addRole(role, username);
} Prevention
- Block reserved role names before calling addRole.
- Do not recreate system-managed roles via the public API.
- Configure anonymous behavior rather than recreating the role.
When it happens
Trigger: Console-side addRole("__nacos_anonymous_role__", username); importing a role set containing the anonymous role via the remote path.
Common situations: Bulk role import without reserved-name filtering; misconfigured sync job replaying default roles.
Related errors
- role '__nacos_anonymous_role__' is reserved by the system
- role 'ROLE_ADMIN' is not permitted to create!
- role 'ROLE_ADMIN' is not permitted to create!
- user '{username}' not found!
- user '{username}' already bound to the role '{role}'!
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/0efdc820f4a7bbb6.
Report an issue: GitHub.