SonarSource/sonarqube · error · ReactivationException

A removed rule with the key

Error message

A removed rule with the key '%s' already exists

What it means

When creating a custom rule, SonarQube may find an existing rule with the same key whose status is REMOVED. RuleCreator.updateExistingRule throws this ReactivationException if the request sets preventReactivation=true, refusing to silently resurrect a removed rule; the exception carries the removed rule's key for auditing.

Solutions

  1. Set preventReactivation=false to allow the removed rule to be restored to READY (the code path then reactivates it).
  2. Choose a different rule key if the removed rule should stay removed.
  3. If intentional, permanently clean the REMOVED rule record before recreating the key.

Example fix

// before
POST /api/rules/create?custom_key=old-rule&prevent_reactivation=true  (removed rule 'old-rule' exists)

// after
POST /api/rules/create?custom_key=old-rule&prevent_reactivation=false
Defensive patterns

Strategy: try-catch

Validate before calling

// check for existing removed rule before create
RuleDto existing = dbClient.ruleDao().selectByKey(dbSession, RuleKey.of(repo, key));
boolean removedExists = existing != null && RuleStatus.REMOVED.equals(existing.getStatus());
if (removedExists && preventReactivation) throw new IllegalStateException("Removed rule exists: " + key);

Try / catch

try { ruleCreator.create(...); } catch (ReactivationException e) { log.warn("Removed rule blocks reactivation: {}", e.ruleKey()); }

Prevention

When it happens

Trigger: Creating (or reactivating) a custom rule via api/rules/create with preventReactivation=true while a rule with the same key exists in REMOVED status.

Common situations: Re-adding a rule that was deleted earlier after a rule-set update; bulk rule imports re-running over previously removed keys; quality-profile reactivations with the safety flag enabled.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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

Appendix: source

Thrown at server/sonar-webserver-common/src/main/java/org/sonar/server/common/rule/RuleCreator.java:273

          .setType(type)
          .setSeverity(severity);
      }
    }
  }

  private void createCustomRuleParams(@Nullable String paramValue, RuleDto ruleDto, RuleParamDto templateRuleParam, DbSession dbSession) {
    RuleParamDto ruleParamDto = RuleParamDto.createFor(ruleDto)
      .setName(templateRuleParam.getName())
      .setType(templateRuleParam.getType())
      .setDescription(templateRuleParam.getDescription())
      .setDefaultValue(paramValue);
    dbClient.ruleDao().insertRuleParam(dbSession, ruleDto, ruleParamDto);
  }

  private RuleDto updateExistingRule(RuleDto ruleDto, NewCustomRule newRule, RuleDto templateRule, DbSession dbSession) {
    if (ruleDto.getStatus().equals(RuleStatus.REMOVED)) {
      if (newRule.isPreventReactivation()) {
        throw new ReactivationException(format("A removed rule with the key '%s' already exists", ruleDto.getKey().rule()), ruleDto.getKey());
      } else {
        ruleDto.setStatus(RuleStatus.READY)
          .setName(newRule.name())
          .replaceRuleDescriptionSectionDtos(Set.of(
            createDefaultRuleDescriptionSection(uuidFactory.create(), newRule.markdownDescription())))
          .setUpdatedAt(system2.now());

        ruleDto.replaceAllDefaultImpacts(Set.of());
        setCleanCodeAttributeAndImpacts(newRule, ruleDto, templateRule);

        dbClient.ruleDao().update(dbSession, ruleDto);
        for (RuleParamDto ruleParamDto : dbClient.ruleDao().selectRuleParamsByRuleKey(dbSession, ruleDto.getKey())) {
          String newValue = Strings.emptyToNull(newRule.parameter(ruleParamDto.getName()));
          ruleParamDto.setDefaultValue(newValue);
          dbClient.ruleDao().updateRuleParam(dbSession, ruleDto, ruleParamDto);
        }
      }
    } else {

View on GitHub (pinned to 184c821202)