elastic/elasticsearch · error · XContentParseException

unable to parse {} with name [{}]: parser didn't match

Error message

unable to parse {} with name [{}]: parser didn't match

What it means

After a name lookup succeeds (entry found), lookupParser calls entry.name.match() to run deprecation logging. If match returns false — which the comment says shouldn't happen because the entry was already located by name — it throws this defensive XContentParseException. Encountering it implies an inconsistency between the lookup map keys and the ParseField.match logic (e.g. a custom ParseField whose match disagrees with its registered name).

Source

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

    // 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. Audit any custom ParseField subclasses involved: match() must return true for the name used as the registry key.
  2. Verify entries are registered under consistent names across RestApiVersions; a mismatch between the lookup map and match() causes this.
  3. If using stock ParseField, this is likely a registry construction bug — check for duplicate registrations clobbering the entry.
Defensive patterns

Strategy: validation

Validate before calling

// for custom ParseField, assert match is consistent with the registered name
ParseField pf = ...;
assert pf.match(name, DeprecationHandler.IGNORE_DEPRECATIONS) : "ParseField.match must accept its registered name";

Try / catch

try {
    Entry e = registry.lookupParser(categoryClass, name, parser);
} catch (XContentParseException ex) {
    if (ex.getMessage().contains("parser didn't match")) {
        // audit custom ParseField.match and registry key consistency
    }
}

Prevention

When it happens

Trigger: A ParseField registered with a name but whose match() implementation rejects that exact name (custom ParseField subclass, or a registration bug). RestApiVersion-specific name resolution where match uses version-dependent logic that diverges from the map key used for lookup.

Common situations: Custom ParseField implementations with non-standard match semantics. Registry corruption during construction (duplicate/overlapping entries). Extremely rare in normal Elasticsearch usage.

Understand the failure class

Related errors


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