SonarSource/sonarqube · error · IllegalArgumentException

User ' ' is not deactivated

Error message

User '%s' is not deactivated

What it means

api/users/anonymize only works on deactivated users: AnonymizeAction.handle loads the user by login and throws IllegalArgumentException if user.isActive(), because anonymizing an active user would break their sessions/assignments expectations. The user record is untouched when this fires.

Solutions

  1. Call POST api/users/deactivate?login=x first, then anonymize
  2. Check the user's active=false status (api/users/search) before anonymizing
  3. If the user was re-activated by mistake, deactivate again before retrying

Example fix

// before
POST /api/users/anonymize?login=jdoe
// after
POST /api/users/deactivate?login=jdoe
POST /api/users/anonymize?login=jdoe
Defensive patterns

Strategy: validation

Validate before calling

const user = await getUser(login);
if (user.active) throw new Error(`Deactivate user '${login}' before anonymizing`);

Type guard

function canAnonymize(user) { return user != null && user.active === false; }

Try / catch

try { await anonymizeUser(login); } catch (e) { if (/is not deactivated/.test(e.message)) { await deactivateUser(login); return anonymizeUser(login); } throw e; }

Prevention

When it happens

Trigger: POST api/users/anonymize?login=x where the user exists but is still active (has not been deactivated via api/users/deactivate).

Common situations: Admin scripts skipping the deactivate step; SCIM/automation assuming anonymize implies deactivation; retrying anonymize for a user that was re-activated.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/AnonymizeAction.java:73

      .setDeprecatedSince("10.4")
      .setChangelog(new Change("10.4", "Deprecated. Use DELETE api/v2/users-management/users/{id}?anonymize=true instead"));

    action.createParam(PARAM_LOGIN)
      .setDescription("User login")
      .setRequired(true)
      .setExampleValue("myuser");
  }

  @Override
  public void handle(Request request, Response response) throws Exception {
    userSession.checkLoggedIn().checkIsSystemAdministrator();
    String login = request.mandatoryParam(PARAM_LOGIN);

    try (DbSession dbSession = dbClient.openSession(false)) {
      UserDto user = dbClient.userDao().selectByLogin(dbSession, login);
      checkFound(user, "User '%s' doesn't exist", login);
      if (user.isActive()) {
        throw new IllegalArgumentException(String.format("User '%s' is not deactivated", login));
      }

      userAnonymizer.anonymize(dbSession, user);
      dbClient.userDao().update(dbSession, user);
      dbSession.commit();
    }

    response.noContent();
  }

}

View on GitHub (pinned to 184c821202)