elastic/elasticsearch · error · XContentParseException
parser for [{}] did not end on {}
Error message
parser for [{}] did not end on {} What it means
Thrown by throwMustEndOn when a field parser has finished consuming its content but the parser's current token is not the expected end token (END_OBJECT or END_ARRAY). This indicates the field's sub-parser read too few or too many tokens, leaving the parser in an inconsistent state relative to the expected token.
Source
Thrown at libs/x-content/src/main/java/org/elasticsearch/xcontent/ObjectParser.java:672
* for having a cheap test.
*/
if (parser.currentToken() != XContentParser.Token.END_ARRAY) {
throwMustEndOn(parser, currentFieldName, XContentParser.Token.END_ARRAY);
}
}
case END_OBJECT, END_ARRAY, FIELD_NAME -> throw throwUnexpectedToken(parser, token);
case VALUE_STRING, VALUE_NUMBER, VALUE_BOOLEAN, VALUE_EMBEDDED_OBJECT, VALUE_NULL -> parseValue(
parser,
fieldParser,
currentFieldName,
value,
context
);
}
}
private static void throwMustEndOn(XContentParser parser, String currentFieldName, XContentParser.Token token) {
throw new XContentParseException(parser.getTokenLocation(), "parser for [" + currentFieldName + "] did not end on " + token);
}
private XContentParseException throwUnexpectedToken(XContentParser parser, XContentParser.Token token) {
return new XContentParseException(parser.getTokenLocation(), "[" + name + "]" + token + " is unexpected");
}
private class FieldParser {
private final Parser<Value, Context> parser;
private final EnumSet<XContentParser.Token> supportedTokens;
private final ParseField parseField;
private final ValueType type;
FieldParser(Parser<Value, Context> parser, EnumSet<XContentParser.Token> supportedTokens, ParseField parseField, ValueType type) {
this.parser = parser;
this.supportedTokens = supportedTokens;
this.parseField = parseField;
this.type = type;
}View on GitHub (pinned to db6a809a66)
Solutions
- If you wrote a custom Parser callback, ensure it consumes exactly the right number of tokens (up to and including the matching END token).
- Verify the declared ValueType matches the actual JSON structure being parsed.
- Check the request body for structural issues like missing closing braces or extra nested objects.
- Use a JSON validator to ensure the structure is well-formed.
Defensive patterns
Strategy: validation
Validate before calling
// Before sending, validate JSON structure is well-formed with matching braces
public static boolean isWellFormed(String json) {
int depth = 0;
boolean inString = false;
for (int i = 0; i < json.length(); i++) {
char c = json.charAt(i);
if (c == '"') inString = !inString;
if (!inString) {
if (c == '{' || c == '[') depth++;
if (c == '}' || c == ']') depth--;
}
}
return depth == 0;
} Try / catch
try {
objectParser.parse(parser, context);
} catch (XContentParseException e) {
if (e.getMessage().contains("did not end on")) {
logger.error("Parser state mismatch: {}", e.getMessage());
return badRequest("Malformed content structure");
}
throw e;
} Prevention
- If writing custom Parser callbacks, test them thoroughly to ensure correct token consumption.
- Validate JSON with a parser/validator before feeding it to ObjectParser.
- Match declared ValueType to the actual JSON structure to avoid token boundary mismatches.
When it happens
Trigger: A custom Parser callback that does not fully consume the sub-structure (e.g., stops reading before END_OBJECT). A declared field whose parser reads a nested object but leaves the parser positioned mid-object. A mismatch between the declared ValueType (which determines expected token boundaries) and the actual content structure.
Common situations: Custom ObjectParser extension with a Parser callback that doesn't consume all tokens. Declaring a field as a single value but providing a multi-value structure. Corruption in the input that causes the tokenizer to produce unexpected token sequences.
Related errors
- [{}] cannot parse field [{}] with value type [{}]
- [{}] Expected START_OBJECT but was: {}
- Required one of fields {}, but none were specified.
- The following fields are not allowed together: {}
- [{}] failed to parse object
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/43242a2591cdec1f.
Report an issue: GitHub.