apache/druid · error · IllegalStateException

Couldn't serialize authenticator userMap!

Error message

Couldn't serialize authenticator userMap!

What it means

BasicAuthUtils.serializeAuthenticatorUserMap writes the authenticator user map to JSON bytes with Jackson. If writeValueAsBytes throws (IOException family), it throws ISE('Couldn't serialize authenticator userMap!'). This is rare since BasicAuthenticatorUser is a simple POJO, but failures indicate a mapper/serialization incompatibility.

Source

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

        userMap = objectMapper.readValue(userMapBytes, AUTHENTICATOR_USER_MAP_TYPE_REFERENCE);
      }
      catch (IOException ioe) {
        throw new RuntimeException("Couldn't deserialize authenticator userMap!", ioe);
      }
    }
    return userMap;
  }

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

  public static Map<String, BasicAuthorizerUser> deserializeAuthorizerUserMap(
      ObjectMapper objectMapper,
      byte[] userMapBytes
  )
  {
    Map<String, BasicAuthorizerUser> userMap;
    if (userMapBytes == null) {
      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);
      }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Ensure the map passed is Map<String, BasicAuthenticatorUser> and built from BasicAuthUtils.deserializeAuthenticatorUserMap
  2. Verify the Jackson ObjectMapper is the Druid-standard mapper (no conflicting modules)
  3. Catch and log the ISE at call sites to identify which map content failed

Example fix

// before
Map<String, BasicAuthorizerUser> m = ...;
byte[] b = BasicAuthUtils.serializeAuthenticatorUserMap(mapper, m);
// after
Map<String, BasicAuthenticatorUser> m = BasicAuthUtils.deserializeAuthenticatorUserMap(mapper, bytes);
byte[] b = BasicAuthUtils.serializeAuthenticatorUserMap(mapper, m);
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the map contains only expected value types
boolean valid = userMap.values().stream().allMatch(v -> v instanceof BasicAuthenticatorUser);

Type guard

boolean isAuthenticatorUserMap(Map<String, ?> m) {
  return m.values().stream().allMatch(BasicAuthenticatorUser.class::isInstance);
}

Try / catch

try {
  byte[] b = BasicAuthUtils.serializeAuthenticatorUserMap(mapper, userMap);
} catch (ISE e) {
  if (e.getMessage().contains("Couldn't serialize authenticator userMap!")) {
    // rebuild map from deserialization and retry
  } else throw e;
}

Prevention

When it happens

Trigger: Saving the authenticator user map when the ObjectMapper lacks a serializer for a contained type or the user map contains a non-serializable object (e.g. wrong generic map passed in).

Common situations: Passing a Map<String, BasicAuthorizerUser> (wrong type) to the authenticator serializer, custom Jackson modules missing, or mixing authorizer/authenticator maps in custom code.

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/9049fa35a68dbba8. Report an issue: GitHub.