elastic/elasticsearch · error · XContentParseException

unknown named object category [{}]

Error message

unknown named object category [{}]

What it means

lookupParser throws when the registry is non-empty (so it isn't the empty-registry case) but the requested category class has no entry map at all for the active REST API version. This means named objects of that category are simply not registered, as opposed to a specific name being unknown.

Source

Thrown at libs/x-content/src/main/java/org/elasticsearch/xcontent/NamedXContentRegistry.java:173

     */
    public boolean hasParser(Class<?> categoryClass, String name, RestApiVersion apiVersion) {
        final Map<Class<?>, Map<String, Entry>> versionMap = registry.get(apiVersion);
        if (versionMap == null) {
            return false;
        }
        final Map<String, Entry> parsers = versionMap.get(categoryClass);
        return parsers != null && parsers.containsKey(name);
    }

    // scope for testing
    public <T> Entry lookupParser(Class<T> categoryClass, String name, XContentParser parser) {
        Map<String, Entry> parsers = registry.getOrDefault(parser.getRestApiVersion(), emptyMap()).get(categoryClass);
        if (parsers == null) {
            if (registry.isEmpty()) {
                // The "empty" registry will never work so we throw a better exception as a hint.
                throw new XContentParseException("named objects are not supported for this parser");
            }
            throw new XContentParseException("unknown named object category [" + categoryClass.getName() + "]");
        }
        Entry entry = parsers.get(name);
        if (entry == null) {
            throw new NamedObjectNotFoundException(parser.getTokenLocation(), "unknown field [" + name + "]", parsers.keySet());
        }
        if (false == entry.name.match(name, parser.getDeprecationHandler())) {
            /* Note that this shouldn't happen because we already looked up the entry using the names but we need to call `match` anyway
             * because it is responsible for logging deprecation warnings. */
            throw new XContentParseException(
                parser.getTokenLocation(),
                "unable to parse " + categoryClass.getSimpleName() + " with name [" + name + "]: parser didn't match"
            );
        }
        return entry;
    }

}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Register the category in the NamedXContentRegistry with the appropriate Entry list, or use a registry that already includes it.
  2. Confirm the category class passed to namedObject is the exact class the entries were registered under (subclass vs superclass mismatches cause this).
  3. Load the module/plugin that contributes that category's named content.
Defensive patterns

Strategy: validation

Validate before calling

// confirm the category is registered for the active REST API version
boolean registered = registry.isRegistered(categoryClass, name); // or check getCategoryNames
if (!registered) { /* register category or pick a registry that includes it */ }

Try / catch

try {
    Entry e = registry.lookupParser(categoryClass, name, parser);
} catch (XContentParseException ex) {
    if (ex.getMessage().startsWith("unknown named object category [")) {
        // register the category or load the contributing module
    }
}

Prevention

When it happens

Trigger: Requesting a named object for a category class (e.g. QueryBuilder.class, Aggregation.class) that has zero registrations in the registry for the current RestApiVersion. Mixing a category the registry was never taught about.

Common situations: Using a category that belongs to a different distribution/module than the one whose registry you hold. Version-skewed parsing where the category exists in a newer module not loaded. Typos in the category class passed to namedObject.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/54ef6bec377550af. Report an issue: GitHub.