apache/druid · error · RuntimeException

Couldn't deserialize authorizer roleMap!

Error message

Couldn't deserialize authorizer roleMap!

What it means

Thrown by BasicAuthUtils.deserializeAuthorizerRoleMap when Jackson cannot read the stored byte array back into a Map<String, BasicAuthorizerRole>. Druid persists role maps as serialized JSON in metadata storage; if those bytes are unreadable or not valid JSON of the expected shape, deserialization fails and this RuntimeException is thrown. It usually means corrupted or malformed persisted data.

Source

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

    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);
      }
    }
    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 {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Log/inspect the raw roleMapBytes and the wrapped IOException to identify the parse failure point
  2. Verify the metadata-store record for the role map is complete valid JSON matching BasicAuthorizerRole
  3. Check whether a version upgrade changed the persisted format and re-run any required migration/upgrade scripts
  4. Restore the role map from a good metadata store backup and re-create roles via the API
Defensive patterns

Strategy: try-catch

Validate before calling

boolean looksLikeRoleMap(byte[] b) { return b != null && b.length > 0 && b[0] == '{'; }

Type guard

boolean isValidRoleMapBytes(byte[] bytes) { try (JsonParser p = jsonMapper.getFactory().createParser(bytes)) { while (p.nextToken() != null) {} return true; } catch (IOException e) { return false; } }

Try / catch

try { Map<String, BasicAuthorizerRole> roles = BasicAuthUtils.deserializeAuthorizerRoleMap(jsonMapper, bytes); } catch (RuntimeException e) { LOG.error(e, "corrupt roleMap bytes; restoring from backup"); roles = restoreFromBackupOrDefault(); }

Prevention

When it happens

Trigger: Reading roleMapBytes from metadata storage that were written by an incompatible version, truncated, corrupted, or are not JSON matching BasicAuthorizerRole's expected shape (including empty bytes that are non-null and non-empty but invalid).

Common situations: Upgrading Druid across schema-incompatible basic-security versions; manual edits to the druid_basic_roles metadata table; interrupted writes leaving partial JSON in the DB.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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