elastic/elasticsearch · error · NamedObjectNotFoundException

unknown field [{}]

Error message

unknown field [{}]

What it means

lookupParser finds the category's entry map but no Entry for the requested name, throwing NamedObjectNotFoundException with the token location and the set of candidate names actually registered for that category. The candidates are meant to suggest the correct name. This is the 'name typo / unsupported name' case as opposed to missing category or empty registry.

Source

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

            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. Check the candidate names in the exception and use the correct registered name.
  2. Install the plugin/module that contributes the named type if it's legitimately expected.
  3. Register the name explicitly if it's a custom named object your code defines.

Example fix

// before: 'avragg' typo, registry only knows 'avg'
{"avragg": {}}
// candidates shown: [avg, sum, max, ...]

// after
{"avg": {}}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate name against registered candidates before lookup
Set<String> known = registry.getRegisteredNamesFor(categoryClass); // hypothetical helper
if (!known.contains(name)) { /* surface candidates to the client */ }

Try / catch

try {
    Entry e = registry.lookupParser(categoryClass, name, parser);
} catch (NamedObjectNotFoundException e) {
    Set<String> candidates = e.getCandidates();
    // suggest closest match / install missing plugin
}

Prevention

When it happens

Trigger: A named object reference (e.g. an aggregation or query type name) uses a name not present in the registry for its category. Typo in the name, a name from a different version, or a name only available in a plugin that isn't installed.

Common situations: Aggregation/query type name typos. Using a named type provided by an unloaded plugin. Version skew where the name existed in an older/newer registry.

Related errors


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