apache/druid · error · IllegalStateException
Couldn't serialize authorizer userMap!
Error message
Couldn't serialize authorizer userMap!
What it means
BasicAuthUtils.serializeAuthorizerUserMap serializes Map<String, BasicAuthorizerUser> to JSON bytes; a Jackson IOException becomes ISE('Couldn't serialize authorizer userMap!'). Indicates the supplied map (or its contents) can't be serialized by the given mapper.
Source
Thrown at extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/BasicAuthUtils.java:178
userMap = new HashMap<>();
} else {
try {
userMap = objectMapper.readValue(userMapBytes, BasicAuthUtils.AUTHORIZER_USER_MAP_TYPE_REFERENCE);
}
catch (IOException ioe) {
throw new RuntimeException("Couldn't deserialize authorizer userMap!", ioe);
}
}
return userMap;
}
public static byte[] serializeAuthorizerUserMap(ObjectMapper objectMapper, Map<String, BasicAuthorizerUser> userMap)
{
try {
return objectMapper.writeValueAsBytes(userMap);
}
catch (IOException ioe) {
throw new ISE(ioe, "Couldn't serialize authorizer userMap!");
}
}
public static Map<String, BasicAuthorizerGroupMapping> deserializeAuthorizerGroupMappingMap(
ObjectMapper objectMapper,
byte[] groupMappingMapBytes
)
{
Map<String, BasicAuthorizerGroupMapping> groupMappingMap;
if (groupMappingMapBytes == null) {
groupMappingMap = new HashMap<>();
} else {
try {
groupMappingMap = objectMapper.readValue(groupMappingMapBytes, BasicAuthUtils.AUTHORIZER_GROUP_MAPPING_MAP_TYPE_REFERENCE);
}
catch (IOException ioe) {
throw new RuntimeException("Couldn't deserialize authorizer groupMappingMap!", ioe);
}View on GitHub (pinned to 9b90983fd2)
Solutions
- Pass a properly typed Map<String, BasicAuthorizerUser> obtained from deserializeAuthorizerUserMap
- Use the standard Druid ObjectMapper configuration
- Add logging around serialization to capture the offending entry
Example fix
// before Map<String, BasicAuthenticatorUser> m = ...; BasicAuthUtils.serializeAuthorizerUserMap(mapper, (Map) m); // after Map<String, BasicAuthorizerUser> m = ...; BasicAuthUtils.serializeAuthorizerUserMap(mapper, m);
Defensive patterns
Strategy: type-guard
Validate before calling
boolean valid = userMap.values().stream().allMatch(v -> v instanceof BasicAuthorizerUser);
Type guard
boolean isAuthorizerUserMap(Map<String, ?> m) {
return m.values().stream().allMatch(BasicAuthorizerUser.class::isInstance);
} Try / catch
try {
byte[] b = BasicAuthUtils.serializeAuthorizerUserMap(mapper, userMap);
} catch (ISE e) {
if (e.getMessage().contains("Couldn't serialize authorizer userMap!")) {
// rebuild the map and retry
} else throw e;
} Prevention
- Pass correctly typed Map<String, BasicAuthorizerUser>
- Do not mix authenticator and authorizer maps
- Use the Druid-standard ObjectMapper in custom code
When it happens
Trigger: Persisting the authorizer user map when the wrong map type or a mapper-incompatible object is supplied.
Common situations: Custom extension code passing authenticator maps or foreign objects into the authorizer serializer; missing Jackson modules in a stripped-down ObjectMapper.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- Couldn't deserialize authenticator userMap!
- Couldn't serialize authenticator userMap!
- Couldn't deserialize authorizer userMap!
- Couldn't deserialize authorizer groupMappingMap!
- Couldn't serialize authorizer groupMappingMap!
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/893307303163e045.
Report an issue: GitHub.