apache/druid · warning

Failed to sanitize SearchResult in context key

Error message

Failed to sanitize SearchResult in context key [%s]

What it means

During OPA authorization, LDAP SearchResult objects found in the request context are sanitized to remove attributes not allowed to be forwarded. If sanitizeSearchResult throws a NamingException (LDAP/JNDI failure while reading attributes), the emitter logs this warning and substitutes an empty map for that context key so authorization can proceed.

Solutions

  1. Verify LDAP connectivity and keep-alive settings between the Druid process and the LDAP server; the sanitized value degrades to an empty map, so expect context attributes to be missing downstream.
  2. Inspect the warn-level NamingException stack trace to identify which attribute or referral failed and fix the LDAP schema/referral configuration.
  3. Increase connection pool timeouts (com.sun.jndi.ldap.connect.timeout / read timeout) so reads do not fail mid-sanitization.
  4. If the empty map breaks OPA policy decisions, update the OPA policy to tolerate a missing/empty context attribute instead of failing the request.

Example fix

// before
sanitizedContext.put(entry.getKey(), Collections.emptyMap());
// after
SearchResult sr = (SearchResult) entry.getValue();
if (sr.getAttributes() != null) {
  sanitizedContext.put(entry.getKey(), sanitizeSearchResult(sr));
} else {
  sanitizedContext.put(entry.getKey(), Collections.emptyMap());
}
Defensive patterns

Strategy: fallback

Validate before calling

if (value instanceof SearchResult) {
  SearchResult sr = (SearchResult) value;
  if (sr.getAttributes() == null) {
    log.warn("SearchResult for key %s has null attributes; will sanitize to empty map", key);
  }
}

Type guard

static boolean isSanitizableSearchResult(Object v) {
  return v instanceof SearchResult && ((SearchResult) v).getAttributes() != null;
}

Try / catch

try {
  ctx.put(key, sanitizeSearchResult((SearchResult) value));
} catch (NamingException e) {
  log.warn(e, "LDAP sanitize failed for key %s; using empty map", key);
  ctx.put(key, Collections.emptyMap());
}

Prevention

When it happens

Trigger: A context entry value is a javax.naming.directory.SearchResult and the underlying LDAP directory rejects the attribute read: closed or timed-out LDAP connection, referral chasing failure, schema violation reading a specific attribute, or a null/invalid SearchResult supplied by an LDAP extension into the auth context.

Common situations: Deployments using LDAP-based authentication feeding the OPA authorizer; misconfigured LDAP connection pools going stale, firewalls dropping idle LDAP connections, or LDAP servers returning partial results/referrals that JNDI cannot follow.

Related errors


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

Appendix: source

Thrown at extensions-contrib/druid-opa-authorizer/src/main/java/org/apache/druid/security/opa/OpaAuthorizer.java:199

    catch (Exception e) {
      return Access.deny("An error occurred: " + e);
    }
  }

  protected Map<String, Object> sanitizeContext(Map<String, Object> context)
  {
    if (context == null || context.isEmpty()) {
      return context;
    }

    final Map<String, Object> sanitizedContext = new HashMap<>();
    for (final Map.Entry<String, Object> entry : context.entrySet()) {
      if (entry.getValue() instanceof SearchResult) {
        try {
          sanitizedContext.put(entry.getKey(), sanitizeSearchResult((SearchResult) entry.getValue()));
        }
        catch (NamingException e) {
          LOG.warn(e, "Failed to sanitize SearchResult in context key [%s]", entry.getKey());
          sanitizedContext.put(entry.getKey(), Collections.emptyMap());
        }
      } else {
        // Keep other types as is, assuming they are serializable or handled by other means
        sanitizedContext.put(entry.getKey(), entry.getValue());
      }
    }
    return sanitizedContext;
  }

  private Map<String, Object> sanitizeSearchResult(SearchResult searchResult) throws NamingException
  {
    final Map<String, Object> sanitized = new HashMap<>();
    sanitized.put("name", searchResult.getName());

    try {
      sanitized.put("nameInNamespace", searchResult.getNameInNamespace());
    }

View on GitHub (pinned to 9b90983fd2)