elastic/elasticsearch · error · IllegalArgumentException
cannot add non-map fields to root of document
Error message
cannot add non-map fields to root of document
What it means
Thrown by JsonProcessor.mergeParsedJson when the parsed JSON value is not a Map (i.e. it was a scalar, array, or null after parsing). The json processor can only merge object-shaped JSON into the document root; non-map values are rejected. IllegalArgumentException guarding document-root integrity.
Source
Thrown at modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/JsonProcessor.java:165
boolean allowDuplicateKeys,
ConflictStrategy conflictStrategy,
boolean strictJsonParsing
) {
Object value = apply(ctx.get(fieldName), allowDuplicateKeys, strictJsonParsing);
mergeParsedJson(ctx, value, conflictStrategy);
}
private static void mergeParsedJson(Map<String, Object> ctx, Object value, ConflictStrategy conflictStrategy) {
if (value instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) value;
if (conflictStrategy == ConflictStrategy.MERGE) {
recursiveMerge(ctx, map);
} else {
ctx.putAll(map);
}
} else {
throw new IllegalArgumentException("cannot add non-map fields to root of document");
}
}
public static void recursiveMerge(Map<String, Object> target, Map<String, Object> from) {
for (String key : from.keySet()) {
if (target.containsKey(key)) {
Object targetValue = target.get(key);
Object fromValue = from.get(key);
if (targetValue instanceof Map && fromValue instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> targetMap = (Map<String, Object>) targetValue;
@SuppressWarnings("unchecked")
Map<String, Object> fromMap = (Map<String, Object>) fromValue;
recursiveMerge(targetMap, fromMap);
} else {
target.put(key, fromValue);
}
} else {View on GitHub (pinned to db6a809a66)
Solutions
- Ensure the source field contains a JSON object (curly-brace) when merging into the document root.
- If a scalar/array is valid, set target_field to a named sub-field instead of root so it becomes the field value.
- Pre-validate or filter documents whose JSON is non-object before the json processor.
Example fix
// before
{"json": {"field": "raw", "target_field": "_source"}}
// raw = '[1,2,3]'
// after
{"json": {"field": "raw", "target_field": "parsed_array"}} Defensive patterns
Strategy: type-guard
Validate before calling
Object parsed = JsonProcessor.apply(rawValue, allowDup, strict);
if (!(parsed instanceof Map)) {
// route scalar/array values to a sub-field instead of root
} Type guard
static boolean isMergeableToRoot(Object v) {
return v instanceof Map;
} Try / catch
try {
JsonProcessor.apply(ctx, fieldName, allowDup, conflictStrategy, strict);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("cannot add non-map fields to root of document")) {
// re-run with a non-root target_field
} else throw e;
} Prevention
- When parsing JSON of unknown shape, target a named sub-field rather than document root.
- Validate the JSON value is an object before merging into root.
- Document expected JSON shape in pipeline descriptions.
When it happens
Trigger: The target_field points to the document root (or merge target is ctx itself) and the parsed JSON value is a scalar, array, or null — e.g. field contains "42" or "[1,2,3]" instead of "{...}".
Common situations: Producer emits a JSON scalar or array where an object was expected; misconfigured target_field pointing at root instead of a sub-field; or non-object JSON payloads.
Related errors
- cannot read binary value
- could not convert value of type [{}] to transport protocol
- field [{}] of type [{}] cannot be cast to a list or map
- The input {} is not valid JSON and the {} parameter is true
- <wrapped IOException>
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/29d8d13ded5f327e.
Report an issue: GitHub.