alibaba/nacos · warning · IllegalArgumentException

role 'ROLE_ADMIN' already exist !

Error message

role 'ROLE_ADMIN' already exist !

What it means

Thrown by addAdminRole(username) when hasGlobalAdminRole() is already true, meaning the ROLE_ADMIN global administrator role already exists in the system. Nacos tracks admin-role presence and refuses to create a second admin binding through this path, enforcing a single-admin invariant. It is an IllegalArgumentException surfaced as a validation error.

Source

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

        }
        
        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!");
        }
        if (hasGlobalAdminRole()) {
            throw new IllegalArgumentException(
                "role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' already exist !");
        }
        
        rolePersistService.addRole(AuthConstants.GLOBAL_ADMIN_ROLE, username);
        getCachedRoleSet().add(AuthConstants.GLOBAL_ADMIN_ROLE);
        markGlobalAdminRolePresent();
    }
    
    @Override
    public void deleteRole(String role, String userName) {
        rejectReservedRole(role);
        rolePersistService.deleteRole(role, userName);
        invalidateUserRoles(userName);
    }
    
    @Override
    public void deleteRole(String role) {
        rejectReservedRole(role);

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Check roleService.hasGlobalAdminRole() (or query existing admin) before calling addAdminRole.
  2. Make admin bootstrap idempotent: skip promotion when an admin already exists.
  3. If you truly need to change the admin user, use the standard user/role admin APIs rather than re-running addAdminRole.

Example fix

// before
roleService.addAdminRole(username); // throws: admin already exists

// after
if (!roleService.hasGlobalAdminRole()) {
    roleService.addAdminRole(username);
}
Defensive patterns

Strategy: validation

Validate before calling

if (roleService.hasGlobalAdminRole()) {
    // admin already configured; skip bootstrap promotion
    return;
}
roleService.addAdminRole(username);

Prevention

When it happens

Trigger: Calling addAdminRole when an admin already exists (e.g. during re-bootstrap against a non-empty database); promoting a second user to admin while one is already configured; rerunning setup scripts against existing state.

Common situations: Re-running an init/bootstrap job against a DB that already has an admin; forgetting the cluster was already initialized; Helm/k8s redeploy that re-attempts admin seeding.

Related errors


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