{"record":{"id":"d2e6674d4e3fd908","repo":"apache/druid","slug":"role-s-does-not-exist","errorCode":null,"errorMessage":"Role [%s] does not exist.","messagePattern":"Role \\[(.+?)\\] does not exist\\.","errorType":"http","errorClass":"BasicSecurityDBResourceException","httpStatus":400,"severity":"error","filePath":"extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/db/updater/CoordinatorBasicAuthorizerMetadataStorageUpdater.java","lineNumber":940,"sourceCode":"    Map<String, BasicAuthorizerRole> roleMap = BasicAuthUtils.deserializeAuthorizerRoleMap(objectMapper, oldValue);\n    if (roleMap.get(roleName) != null) {\n      throw new BasicSecurityDBResourceException(\"Role [%s] already exists.\", roleName);\n    } else {\n      roleMap.put(roleName, new BasicAuthorizerRole(roleName, null));\n    }\n    byte[] newValue = BasicAuthUtils.serializeAuthorizerRoleMap(objectMapper, roleMap);\n    return tryUpdateRoleMap(prefix, roleMap, oldValue, newValue);\n  }\n\n  private boolean deleteRoleOnce(String prefix, String roleName)\n  {\n    byte[] oldRoleMapValue = getCurrentRoleMapBytes(prefix);\n    Map<String, BasicAuthorizerRole> roleMap = BasicAuthUtils.deserializeAuthorizerRoleMap(\n        objectMapper,\n        oldRoleMapValue\n    );\n    if (roleMap.get(roleName) == null) {\n      throw new BasicSecurityDBResourceException(\"Role [%s] does not exist.\", roleName);\n    } else {\n      roleMap.remove(roleName);\n    }\n\n    byte[] oldUserMapValue = getCurrentUserMapBytes(prefix);\n    Map<String, BasicAuthorizerUser> userMap = BasicAuthUtils.deserializeAuthorizerUserMap(\n        objectMapper,\n        oldUserMapValue\n    );\n    for (BasicAuthorizerUser user : userMap.values()) {\n      user.getRoles().remove(roleName);\n    }\n    byte[] newUserMapValue = BasicAuthUtils.serializeAuthorizerUserMap(objectMapper, userMap);\n\n    byte[] oldGroupMapValue = getCurrentGroupMappingMapBytes(prefix);\n    Map<String, BasicAuthorizerGroupMapping> groupMap = BasicAuthUtils.deserializeAuthorizerGroupMappingMap(\n        objectMapper,\n        oldGroupMapValue","sourceCodeStart":922,"sourceCodeEnd":958,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/db/updater/CoordinatorBasicAuthorizerMetadataStorageUpdater.java#L922-L958","documentation":"BasicSecurityDBResourceException thrown during role deletion when the role is not present in the authorizer's role map. The coordinator validates the role exists before removing it and before cleaning up user assignments, aborting the whole operation if it is missing. Signals a stale name reference or wrong authorizer, not a store failure.","triggerScenarios":"DELETE /druid-ext/basic-security/authorization/db/<authorizer>/roles/<roleName> where roleName is absent from the role map.","commonSituations":"Double-delete in cleanup scripts; role already removed by another admin; typo or wrong authorizer name in the URL; roles recreated under different names after a config migration.","solutions":["Confirm the role exists with GET /druid-ext/basic-security/authorization/db/<authorizer>/roles before deleting","Make deletion idempotent in scripts by tolerating 'does not exist'","Verify the authorizer name in the request path","Re-create the role if it was deleted accidentally"],"exampleFix":"// before\nclient.deleteRole(\"default\", \"readRole\");\n// after\nif (roleExists(\"default\", \"readRole\")) {\n  client.deleteRole(\"default\", \"readRole\");\n}","handlingStrategy":"validation","validationCode":"boolean exists = getRoles(\"default\").contains(roleName);\nif (!exists) log.warn(\"Role absent, skipping delete: \" + roleName);","typeGuard":null,"tryCatchPattern":"try {\n  client.deleteRole(\"default\", roleName);\n} catch (BasicSecurityDBResourceException e) {\n  if (e.getMessage().contains(\"does not exist\")) {\n    log.info(\"Role {} already deleted\", roleName);\n  } else { throw e; }\n}","preventionTips":["Confirm role exists before delete","Make teardown scripts tolerant of missing roles","Use exact role names from a shared config, not hand-typed URLs"],"tags":["security","rest-api","delete"],"backgroundTag":"entity-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}