elastic/elasticsearch · error · IllegalArgumentException

<wrapped IOException>

Error message

<wrapped IOException>

What it means

JsonProcessor.apply wraps any IOException from the XContentParser in an IllegalArgumentException with the placeholder message. Since the parser reads from an in-memory string, an IOException indicates a parser-level fault rather than a real I/O issue. The original IOException is the cause of the thrown IllegalArgumentException.

Solutions

  1. Inspect the wrapped IOException cause in server logs for the specific parser failure.
  2. Validate the input field is well-formed JSON before invoking the json processor.
  3. If the data is legitimately non-JSON, route it differently or pre-clean it.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate JSON well-formedness with the same parser
try (XContentParser p = JsonXContent.jsonXContent.createParser(
        XContentParserConfiguration.EMPTY, value)) {
    while (p.nextToken() != null) {}
} catch (IOException ioe) {
    // value is not parseable — handle before invoking processor
}

Try / catch

try {
    JsonProcessor.apply(value, allowDup, strict);
} catch (IllegalArgumentException e) {
    if (e.getCause() instanceof IOException) {
        // log cause and route to failure store
    } else throw e;
}

Prevention

When it happens

Trigger: The JSON parser threw an IOException parsing the fieldValue string — typically malformed JSON that fails during tokenization rather than grammar validation.

Common situations: Truncated or corrupted JSON in the field, encoding issues (non-UTF8 bytes decoded wrongly), or parser bugs.

Related errors


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

Appendix: source

Thrown at modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/JsonProcessor.java:140

                /*
                 * If strict JSON parsing is disabled, then once we've found the first token then we move on. For example for the string
                 * "123 \"foo\"" we would just return the first token, 123. However, if strict parsing is enabled (which it is by default),
                 * then we check to see whether there are any more tokens at this point. We expect the next token to be null. If there is
                 * another token or if the parser blows up, then we know we had invalid JSON and we alert the user with an
                 * IllegalArgumentException.
                 */
                try {
                    token = parser.nextToken();
                } catch (IllegalArgumentException e) {
                    throw new IllegalArgumentException(errorMessage, e);
                }
                if (token != null) {
                    throw new IllegalArgumentException(errorMessage);
                }
            }
            return value;
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static void apply(
        Map<String, Object> ctx,
        String fieldName,
        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;

View on GitHub (pinned to db6a809a66)