apache/druid · error · IllegalStateException

Could not delete group mapping [%s] due to concurrent update

Error message

Could not delete group mapping [%s] due to concurrent update contention.

What it means

The updater failed to delete an authorization group mapping because every compare-and-swap attempt on the group mapping map lost to a concurrent writer, exhausting numRetries. Each retry re-reads the current map and re-applies the removal; persistent losers mean another client is continuously mutating the same map. The ISE is thrown after the retry loop with the contested group mapping name.

Source

Thrown at extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/db/updater/CoordinatorBasicAuthorizerMetadataStorageUpdater.java:726

  }

  private void deleteGroupMappingInternal(String prefix, String groupMappingName)
  {
    int attempts = 0;
    while (attempts < numRetries) {
      if (deleteGroupMappingOnce(prefix, groupMappingName)) {
        return;
      } else {
        attempts++;
      }
      try {
        Thread.sleep(ThreadLocalRandom.current().nextLong(UPDATE_RETRY_DELAY));
      }
      catch (InterruptedException ie) {
        throw new RuntimeException(ie);
      }
    }
    throw new ISE("Could not delete group mapping [%s] due to concurrent update contention.", groupMappingName);
  }

  private void createRoleInternal(String prefix, String roleName)
  {
    int attempts = 0;
    while (attempts < numRetries) {
      if (createRoleOnce(prefix, roleName)) {
        return;
      } else {
        attempts++;
      }
      try {
        Thread.sleep(ThreadLocalRandom.current().nextLong(UPDATE_RETRY_DELAY));
      }
      catch (InterruptedException ie) {
        throw new RuntimeException(ie);
      }
    }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Retry the deleteGroupMapping call after a short delay.
  2. Ensure a single leader/writer performs authorization metadata updates for this authorizer.
  3. Rate-limit or serialize group mapping mutations from automation tooling.
  4. Raise numRetries for the updater if concurrent updates are routine.
  5. Check metadata storage latency; slow writes increase CAS failure rates.

Example fix

// before
groupMappings.forEach(gm -> client.deleteGroupMapping(prefix, gm));
// after: retry on contention
for (final String gm : groupMappings) {
  await.untilAsserted(() -> client.deleteGroupMapping(prefix, gm));
}
Defensive patterns

Strategy: retry

Validate before calling

// Check the mapping still exists before deleting
byte[] map = curator.getData().forPath(groupMappingPath(prefix));
if (BasicAuthUtils.deserializeAuthorizerGroupMappingMap(mapper, map).get(name) == null) return;

Try / catch

try {
  updater.deleteGroupMapping(prefix, name);
} catch (IJSE e) {
  await.atMost(Duration.ofSeconds(10)).untilAsserted(
      () -> updater.deleteGroupMapping(prefix, name));
}

Prevention

When it happens

Trigger: Calling deleteGroupMapping while other writers repeatedly update the same authorizer prefix's group mapping map so tryUpdateGroupMappingMap CAS fails for all numRetries attempts.

Common situations: Two admin sessions or automation jobs deleting/updating group mappings at once; a coordinator leader failover leaving a second active writer; bursty API traffic against basic-security endpoints backed by a laggy metadata store.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/bc51e027aebf6573. Report an issue: GitHub.