alibaba/nacos · info · IllegalArgumentException
user '{username}' already bound to the role '{role}'!
Error message
user '{username}' already bound to the role '{role}'! What it means
Thrown by addRole when isUserBoundToRole(role, username) is already true, i.e. the user already holds that exact role. Nacos rejects duplicate role bindings to keep the role set unique and avoid redundant permission inheritance. The check runs after the reserved-role and existence checks, just before persisting.
Source
Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceDirectImpl.java:140
@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!");
}
if (hasGlobalAdminRole()) {
throw new IllegalArgumentException(
"role '" + AuthConstants.GLOBAL_ADMIN_ROLE + "' already exist !");
}
View on GitHub (pinned to 9b989acdf1)
Solutions
- Before granting, check roleService.getRoles(username) (or isUserBoundToRole) and skip if already present.
- Make provisioning idempotent: treat 'already bound' as success rather than retrying.
- Guard the UI/submit button against duplicate submissions.
Example fix
// before
roleService.addRole(role, username); // throws if already bound
// after
if (!roleService.isUserBoundToRole(role, username)) {
roleService.addRole(role, username);
} Defensive patterns
Strategy: validation
Validate before calling
if (roleService.isUserBoundToRole(role, username)) {
// already granted; treat as success (idempotent)
return;
}
roleService.addRole(role, username); Prevention
- Make role-grant operations idempotent by checking existing bindings first.
- Disable submit buttons after first click to prevent duplicate requests.
- In retry loops, treat 'already bound' as a successful terminal state.
When it happens
Trigger: Calling addRole for a role the user already has; double-submitting a role-grant form; a retry loop that re-runs a successful grant after a transient error; idempotency-unaware provisioning scripts.
Common situations: See trigger scenarios.
Related errors
- role 'ROLE_ADMIN' already exist !
- user ' + username + ' already exist!
- user '{username}' not found!
- role 'ROLE_ADMIN' is not permitted to create!
- role '__nacos_anonymous_role__' is reserved by the system
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/e103ac2be46f4a3b.
Report an issue: GitHub.