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

  1. Inspect the wrapped IOException cause to identify the failing field/type
  2. Use the fully configured Druid ObjectMapper rather than a bare new ObjectMapper()
  3. Fix custom role classes' Jackson annotations (add @JsonProperty/@JsonTypeInfo as needed)
  4. 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

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


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