apache/druid · error · IllegalStateException
Couldn't serialize authorizer roleMap!
Error message
Couldn't serialize authorizer roleMap!
What it means
Thrown by BasicAuthUtils.serializeAuthorizerRoleMap when Jackson fails to convert the authorizer role map into bytes for persistence or cache notification. The role map is serialized whenever roles are updated and pushed to metadata storage; an IOException on that write surfaces as this ISE. Root causes are almost always in the object graph or the mapper configuration.
Source
Thrown at extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/BasicAuthUtils.java:236
roleMap = new HashMap<>();
} else {
try {
roleMap = objectMapper.readValue(roleMapBytes, BasicAuthUtils.AUTHORIZER_ROLE_MAP_TYPE_REFERENCE);
}
catch (IOException ioe) {
throw new RuntimeException("Couldn't deserialize authorizer roleMap!", ioe);
}
}
return roleMap;
}
public static byte[] serializeAuthorizerRoleMap(ObjectMapper objectMapper, Map<String, BasicAuthorizerRole> roleMap)
{
try {
return objectMapper.writeValueAsBytes(roleMap);
}
catch (IOException ioe) {
throw new ISE(ioe, "Couldn't serialize authorizer roleMap!");
}
}
public static void maybeInitialize(final RetryUtils.Task<?> task)
{
try {
RetryUtils.retry(task, SHOULD_RETRY_INIT, MAX_INIT_RETRIES);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Inspect the wrapped IOException cause to identify the failing field/type
- Use the fully configured Druid ObjectMapper rather than a bare new ObjectMapper()
- Fix custom role classes' Jackson annotations (add @JsonProperty/@JsonTypeInfo as needed)
- Retry the role update once state is corrected
Example fix
// before
return objectMapper.writeValueAsBytes(roleMap);
// after
try { return objectMapper.writeValueAsBytes(roleMap); } catch (IOException ioe) { throw new ISE(ioe, "Couldn't serialize authorizer roleMap!"); } // ensure objectMapper is the Druid-injected mapper Defensive patterns
Strategy: try-catch
Validate before calling
if (roleMap == null || roleMap.isEmpty()) { throw new IllegalArgumentException("roleMap empty"); }
roleMap.values().forEach(r -> { if (!jsonMapper.canSerialize(r.getClass())) { throw new IllegalArgumentException("unserializable role class: " + r.getClass()); } }); Type guard
boolean isSerializable(ObjectMapper m, Object o) { return m.canSerialize(o.getClass()); } Try / catch
try { byte[] b = BasicAuthUtils.serializeAuthorizerRoleMap(jsonMapper, roleMap); } catch (ISE e) { LOG.error(e, "roleMap serialization failed"); throw e; } Prevention
- Use the injected Druid ObjectMapper for all role-map serialization
- Add round-trip serialize/deserialize tests for custom BasicAuthorizerRole subclasses
- Avoid storing transient/contextual state inside role objects
- Log the wrapped IOException cause for quick diagnosis
When it happens
Trigger: Calling serializeAuthorizerRoleMap with a Map<String, BasicAuthorizerRole> containing values Jackson cannot serialize (custom role subclasses without serializers, cyclic references, or a mapper missing required modules).
Common situations: Custom BasicAuthorizerRole implementations lacking Jackson annotations; passing a freshly constructed ObjectMapper instead of the injected Druid jsonMapper; corrupted in-memory role maps after failed updates.
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 serialize authorizer groupMappingMap!
- Couldn't deserialize authenticator userMap!
- Couldn't serialize authenticator userMap!
- Couldn't deserialize authorizer userMap!
- Couldn't serialize authorizer userMap!
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/d73b64c7e54b1a65.
Report an issue: GitHub.