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
- Retry the deleteGroupMapping call after a short delay.
- Ensure a single leader/writer performs authorization metadata updates for this authorizer.
- Rate-limit or serialize group mapping mutations from automation tooling.
- Raise numRetries for the updater if concurrent updates are routine.
- 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
- Ensure single-writer (leader-only) metadata updates
- Avoid concurrent delete+update on the same group mapping
- Apply exponential/randomized backoff on retries
- Raise numRetries when concurrent admins are expected
- Watch metadata storage health
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
- Could not create group mapping [%s] due to concurrent update
- Could not create role [%s] due to concurrent update contenti
- Could not delete role [%s] due to concurrent update contenti
- Could not assign role [%s] to user [%s] due to concurrent up
- Could not unassign role [%s] from user [%s] due to concurren
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/bc51e027aebf6573.
Report an issue: GitHub.