SonarSource/sonarqube · error · IllegalArgumentException

An DevOps Platform setting with key '%s' already exists

Error message

An DevOps Platform setting with key '%s' already exists

What it means

IllegalArgumentException from AlmSettingsSupport.checkAlmSettingDoesNotAlreadyExist, thrown by all create*Setting WS handlers when an ALM setting with the same key already exists in ALM_SETTINGS. Keys are unique identifiers for DevOps Platform configurations.

Source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/almsettings/ws/AlmSettingsSupport.java:86

  // persisting more than one ALM setting per family.
  private final ReentrantLock almSettingCreationLock = new ReentrantLock();

  public AlmSettingsSupport(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder,
    MultipleAlmFeature multipleAlmFeature) {
    this.dbClient = dbClient;
    this.userSession = userSession;
    this.componentFinder = componentFinder;
    this.multipleAlmFeature = multipleAlmFeature;
  }

  DbClient getDbClient() {
    return dbClient;
  }

  public void checkAlmSettingDoesNotAlreadyExist(DbSession dbSession, String almSetting) {
    dbClient.almSettingDao().selectByKey(dbSession, almSetting)
      .ifPresent(a -> {
        throw new IllegalArgumentException(format("An DevOps Platform setting with key '%s' already exists", a.getKey()));
      });
  }

  public void checkAlmMultipleFeatureEnabled(DbSession dbSession, ALM alm) {
    if (!multipleAlmFeature.isAvailable() && !dbClient.almSettingDao().selectByAlm(dbSession, alm).isEmpty()) {
      throw BadRequestException.create("A " + alm + " setting is already defined");
    }
  }

  /**
   * Wraps an ALM setting creation in the JVM-wide lock that guarantees the check-then-insert
   * of {@link #checkAlmMultipleFeatureEnabled(DbSession, ALM)} is atomic. Callers must commit
   * inside the lambda so the row is visible before the lock is released. Enterprise/Data Center
   * editions still take the lock — the count check inside is a no-op there, so contention is
   * limited to admin ALM setup, which is rare.
   */
  public void withAlmSettingCreationLock(Runnable action) {
    almSettingCreationLock.lock();

View on GitHub (pinned to 184c821202)

Solutions

  1. Choose a different, unique key for the new configuration
  2. Delete or update the existing setting instead of creating a duplicate
  3. If updating is intended, call the update_alm_settings endpoint rather than create

Example fix

// before
POST /api/alm_settings/create_github key=github (already exists)
// after
POST /api/alm_settings/create_github key=github-team-a
Defensive patterns

Strategy: validation

Validate before calling

const list = await ws.get('api/alm_settings/list');
if (list.almSettings.some(s => s.key === newKey)) {
  throw new Error(`Key '${newKey}' already exists; pick another or update the existing setting`);
}

Type guard

const keyIsFree = (list, key) => !list.almSettings.some(s => s.key === key);

Try / catch

try {
  await ws.post('api/alm_settings/create_github', {key, url});
} catch (e) {
  if (e.status === 400 && /already exists/.test(e.message)) {
    await ws.post('api/alm_settings/update_github', {key, url}); // idempotent path
  } else { throw e; }
}

Prevention

When it happens

Trigger: POST api/alm_settings/create_azure|create_gitlab|create_bitbucket|create_bitbucketcloud|create_github with a key that already exists in the table.

Common situations: Re-running an infrastructure-as-code script without unique keys; re-creating a config after a partial delete; name collisions between teams.

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/9395ee61ce92d54f. Report an issue: GitHub.