SonarSource/sonarqube · error · IllegalStateException

Cannot create unique login for user name

Error message

Cannot create unique login for user name 

What it means

UserUpdater.generateUniqueLogin() derives a login from the user's display name by slugging it and appending a random number, retrying until the login is not already taken in the DB. If no unique login can be produced within the retry budget, it throws IllegalStateException('Cannot create unique login for user name ...').

Source

Thrown at server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserUpdater.java:195

      userDto.setScmAccounts(scmAccounts);
    }

    setExternalIdentity(dbSession, userDto, ExternalIdentityLocal.fromExternalIdentity(newUser.externalIdentity()));

    checkRequest(messages.isEmpty(), messages);
    return userDto;
  }

  private String generateUniqueLogin(DbSession dbSession, String userName) {
    String slugName = slugify(userName);
    for (int i = 0; i < 10; i++) {
      String login = slugName + random.nextInt(100_000);
      UserDto existingUser = dbClient.userDao().selectByLogin(dbSession, login);
      if (existingUser == null) {
        return login;
      }
    }
    throw new IllegalStateException("Cannot create unique login for user name " + userName);
  }

  private boolean updateDto(DbSession dbSession, UpdateUser update, UserDto dto) {
    checkRequestedLocalStateIsConsistent(update, dto);
    List<String> messages = newArrayList();
    boolean changed = updateLogin(dbSession, update, dto, messages);
    changed |= updateName(update, dto, messages);
    changed |= updateEmail(update, dto, messages);
    changed |= updateExternalIdentity(dbSession, update, dto);
    changed |= updatePassword(dbSession, update, dto, messages);
    changed |= updateScmAccounts(dbSession, update, dto, messages);
    checkRequest(messages.isEmpty(), messages);
    return changed;
  }

  private static void checkRequestedLocalStateIsConsistent(UpdateUser update, UserDto dto) {
    if (!update.isLocalChanged() || update.local() == null) {
      return;

View on GitHub (pinned to 184c821202)

Solutions

  1. Check the users table for login collisions with the slugified name and clean up duplicate/inactive accounts
  2. Create the user explicitly with a unique 'login' parameter instead of relying on auto-generation from the name
  3. Retry the operation — the random suffix makes the collision transient
  4. If provisioning thousands of same-named users, change strategy to derive logins from email or a counter rather than the name

Example fix

// before
curl -X POST 'http://sonar/api/users/create?name=John%20Doe'   # login auto-generated
// after
curl -X POST 'http://sonar/api/users/create?login=john.doe.42&name=John%20Doe'
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check login availability before auto-generation paths
UserDto existing = dbClient.userDao().selectByLogin(dbSession, desiredLogin);
if (existing != null) { /* choose a different explicit login */ }

Type guard

null

Try / catch

try {
  userUpdater.createAndCommit(dbSession, request, context);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Cannot create unique login")) {
    // retry with explicit unique login
  } else throw e;
}

Prevention

When it happens

Trigger: Calling user creation (createDto via ws api/users/create, provisioning plugin, or SCIM) when the derived login space is saturated — i.e. thousands of existing users collide with slugName + 0..99999 suffixes.

Common situations: Bulk user provisioning (LDAP/SCIM sync) with many users sharing the same common name; extremely narrow retry bound exhausted on a dense user table.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/4468abf5dc291895. Report an issue: GitHub.