apache/druid · error · IllegalStateException

Couldn't serialize authorizer groupMappingMap!

Error message

Couldn't serialize authorizer groupMappingMap!

What it means

Thrown by BasicAuthUtils.serializeAuthorizerGroupMappingMap when Jackson's ObjectMapper fails to write the authorizer group-mapping map to a byte array. Druid serializes group mappings before persisting them in metadata storage or broadcasting cache updates; an IOException during that write is wrapped in this IllegalStateException. It almost always indicates a serialization configuration or object-graph problem, not user input.

Source

Thrown at extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/BasicAuthUtils.java:207

      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);
      }
    }
    return groupMappingMap;
  }

  public static byte[] serializeAuthorizerGroupMappingMap(ObjectMapper objectMapper, Map<String, BasicAuthorizerGroupMapping> groupMappingMap)
  {
    try {
      return objectMapper.writeValueAsBytes(groupMappingMap);
    }
    catch (IOException ioe) {
      throw new ISE(ioe, "Couldn't serialize authorizer groupMappingMap!");
    }
  }

  public static Map<String, BasicAuthorizerRole> deserializeAuthorizerRoleMap(
      ObjectMapper objectMapper,
      byte[] roleMapBytes
  )
  {
    Map<String, BasicAuthorizerRole> roleMap;
    if (roleMapBytes == null) {
      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);
      }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Inspect the wrapped IOException cause chain to find which field or type failed serialization
  2. Ensure the ObjectMapper passed in is the fully-initialized Druid mapper (with all Jackson modules registered)
  3. Check any custom BasicAuthorizerGroupMapping implementations for non-serializable fields or missing @JsonSerialize/@JsonProperty annotations
  4. If transient, re-trigger the config update; if persistent, fix the offending object graph

Example fix

// before
byte[] bytes = BasicAuthUtils.serializeAuthorizerGroupMappingMap(new ObjectMapper(), groupMappingMap);
// after
byte[] bytes = BasicAuthUtils.serializeAuthorizerGroupMappingMap(jsonMapper, groupMappingMap); // jsonMapper = fully configured Druid ObjectMapper
Defensive patterns

Strategy: try-catch

Validate before calling

if (groupMappingMap == null || groupMappingMap.isEmpty()) { throw new IllegalArgumentException("groupMappingMap empty"); }
groupMappingMap.values().forEach(vm -> { if (vm.getClass().getPackage().getName().startsWith("org.apache.druid.security.basic") && !vm.getClass().getName().equals("org.apache.druid.security.basic.BasicAuthorizerGroupMapping")) { throw new IllegalArgumentException("custom mapping class may not be Jackson-serializable: " + vm.getClass()); } });

Type guard

boolean isSerializable(ObjectMapper m, Object o) { try { m.canSerialize(o.getClass()); return true; } catch (Exception e) { return false; } }

Try / catch

try { byte[] b = BasicAuthUtils.serializeAuthorizerGroupMappingMap(jsonMapper, groupMappingMap); } catch (ISE e) { LOG.error(e, "group-mapping serialization failed; check custom mapping classes and mapper config"); throw e; }

Prevention

When it happens

Trigger: Calling serializeAuthorizerGroupMappingMap with a groupMappingMap whose BasicAuthorizerGroupMapping objects fail Jackson serialization (e.g. self-referencing structures, an ObjectMapper misconfigured for the type, or an underlying JsonSerializer throwing IOException).

Common situations: Custom BasicAuthorizerGroupMapping implementations lacking proper Jackson annotations; corrupted in-memory state after a partial config update; using a raw ObjectMapper without Druid modules registered.

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


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/bd4b326a9ccc20d6. Report an issue: GitHub.