alibaba/nacos · warning · IllegalArgumentException

role 'ROLE_ADMIN' is not permitted to create!

Error message

role 'ROLE_ADMIN' is not permitted to create!

What it means

Thrown by NacosRoleServiceRemoteImpl.addRole (the remote/console path) when the role name equals GLOBAL_ADMIN_ROLE ("ROLE_ADMIN"). Identical guard to the direct impl: the admin role must be granted via addAdminRole, never via the generic role-add. The check is local to the console node before it even forwards the request, so no remote call is made.

Source

Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceRemoteImpl.java:170

            return result.getData();
        } catch (NacosException e) {
            throw new NacosRuntimeException(e.getErrCode(), e.getErrMsg());
        } catch (Exception unpectedException) {
            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,

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Use roleService.addAdminRole(username) to grant admin privileges.
  2. Filter ROLE_ADMIN out of any role list passed to addRole.
  3. Treat reserved role names as non-creatable in your provisioning logic.

Example fix

// before
roleService.addRole("ROLE_ADMIN", username); // rejected locally

// after
roleService.addAdminRole(username);
Defensive patterns

Strategy: validation

Validate before calling

if (AuthConstants.GLOBAL_ADMIN_ROLE.equals(role)) {
    roleService.addAdminRole(username);
} else {
    roleService.addRole(role, username);
}

Prevention

When it happens

Trigger: Console-side addRole("ROLE_ADMIN", username); seeding roles from a catalog that includes the admin role via the remote impl.

Common situations: Console deployment forwarding auth ops attempting to create the admin role through the wrong endpoint; automation that does not filter reserved names.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/95b9d19b06c91e30. Report an issue: GitHub.