{"record":{"id":"6e81cecd4cba8a75","repo":"apache/druid","slug":"couldn-t-deserialize-authorizer-usermap","errorCode":null,"errorMessage":"Couldn't deserialize authorizer userMap!","messagePattern":"Couldn't deserialize authorizer userMap!","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/BasicAuthUtils.java","lineNumber":166,"sourceCode":"    catch (IOException ioe) {\n      throw new ISE(ioe, \"Couldn't serialize authenticator userMap!\");\n    }\n  }\n\n  public static Map<String, BasicAuthorizerUser> deserializeAuthorizerUserMap(\n      ObjectMapper objectMapper,\n      byte[] userMapBytes\n  )\n  {\n    Map<String, BasicAuthorizerUser> userMap;\n    if (userMapBytes == null) {\n      userMap = new HashMap<>();\n    } else {\n      try {\n        userMap = objectMapper.readValue(userMapBytes, BasicAuthUtils.AUTHORIZER_USER_MAP_TYPE_REFERENCE);\n      }\n      catch (IOException ioe) {\n        throw new RuntimeException(\"Couldn't deserialize authorizer userMap!\", ioe);\n      }\n    }\n    return userMap;\n  }\n\n  public static byte[] serializeAuthorizerUserMap(ObjectMapper objectMapper, Map<String, BasicAuthorizerUser> userMap)\n  {\n    try {\n      return objectMapper.writeValueAsBytes(userMap);\n    }\n    catch (IOException ioe) {\n      throw new ISE(ioe, \"Couldn't serialize authorizer userMap!\");\n    }\n  }\n\n  public static Map<String, BasicAuthorizerGroupMapping> deserializeAuthorizerGroupMappingMap(\n      ObjectMapper objectMapper,\n      byte[] groupMappingMapBytes","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/BasicAuthUtils.java#L148-L184","documentation":"BasicAuthUtils.deserializeAuthorizerUserMap parses stored bytes into Map<String, BasicAuthorizerUser> for authorizers. On Jackson IOException it wraps in RuntimeException('Couldn't deserialize authorizer userMap!'), meaning the persisted authorizer user blob is unreadable or schema-incompatible.","triggerScenarios":"Loading the authorizer userMap from metadata storage when bytes are corrupt, hand-edited, or produced by an incompatible Druid version.","commonSituations":"Partial writes during coordinator failover, manual DB edits, version skew across nodes changing user record shape.","solutions":["Re-save authorizer users through the security API to regenerate valid JSON","Check metadata storage for corrupt rows and restore from backup","Align basic-security extension versions across the cluster"],"exampleFix":"// before\n// corrupt row for authorizer userMap\n// after\ncurl -X POST http://coordinator:8084/druid-ext/basic-security/authorization/db/auth_groups/users/bob -H'Content-Type: application/json' -d '{...}'","handlingStrategy":"try-catch","validationCode":"if (bytes != null && bytes.length > 0) {\n  mapper.readTree(bytes); // fail fast on corrupt JSON\n}","typeGuard":null,"tryCatchPattern":"try {\n  Map<String, BasicAuthorizerUser> users = BasicAuthUtils.deserializeAuthorizerUserMap(mapper, bytes);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"Couldn't deserialize authorizer userMap!\")) {\n    users = new HashMap<>(); // or restore from backup\n  } else throw e;\n}","preventionTips":["Avoid manual edits to authorizer userMap rows","Re-save authorizer users through the REST API after version changes","Maintain metadata-store backups","Keep extension versions aligned across nodes"],"tags":["java","security","jackson","serialization"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}