apache/flink · error · org.apache.flink.formats.json.JsonParseException

Fail to deserialize at field: %s.

Error message

Fail to deserialize at field: %s.

What it means

JsonParseException thrown per-field by createRowConverter when a named field's conversion throws any Throwable. Note the cause is deliberately not attached — only the field name is reported — so you must reproduce/inspect the payload to learn the underlying reason (type mismatch, number format, etc.). It fires before ignoreParseErrors is consulted at the outer layer, which then either wraps it as 'Failed to deserialize JSON' or skips the row.

Source

Thrown at flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/JsonParserToRowDataConverters.java:426

            }
            int arity = nameIdxMap.size();
            GenericRowData row = new GenericRowData(arity);
            int cnt = 0;
            jp.nextToken();
            while (jp.currentToken() != JsonToken.END_OBJECT) {
                if (cnt >= arity) {
                    skipToNextField(jp);
                    continue;
                }
                String fieldName = jp.getText();
                jp.nextToken();
                Integer idx = nameIdxMap.get(fieldName);
                if (idx != null) {
                    try {
                        Object convertField = fieldConverters[idx].convert(jp);
                        row.setField(idx, convertField);
                    } catch (Throwable t) {
                        throw new JsonParseException(
                                String.format("Fail to deserialize at field: %s.", fieldName));
                    }
                    jp.nextToken();
                    cnt++;
                } else {
                    skipToNextField(jp);
                }
            }
            if (cnt < arity && failOnMissingField) {
                throw new JsonParseException("Some field is missing in the JSON data.");
            }
            return row;
        };
    }

    public static void skipToNextField(JsonParser jp) throws IOException {
        switch (jp.currentToken()) {
            case START_OBJECT:

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Look at the field named in the message and the raw record from the outer 'Failed to deserialize JSON' wrapper (or DEBUG logs with ignore-parse-errors) to identify the value
  2. Adjust that column's DDL type or the 'timestamp-format' option to match reality
  3. Fix the producer data; or set 'json.ignore-parse-errors'='true' to skip bad rows

Example fix

-- before: data contains "amount": "1,024.50"
amount DECIMAL(10,2)

-- after: normalize at producer, or ingest as string and clean downstream
amount STRING
Defensive patterns

Strategy: try-catch

Try / catch

catch (IOException wrapped) { // outer 'Failed to deserialize JSON'
    Throwable cause = wrapped.getCause(); // JsonParseException 'Fail to deserialize at field: X'
    String field = extractFieldName(cause.getMessage());
    deadLetter(record, field);
}

Prevention

When it happens

Trigger: A field's JSON value cannot convert to its declared type: string 'abc' into INT, out-of-range numbers, wrong nested shape (errors 1371-1375 surface here as field failures when nested inside a row).

Common situations: Schema drift (producer adds/changes field types); locale-dependent number formats in strings; nulls in non-nullable positions handled by a later layer; timestamps in an unexpected format vs the configured timestamp-format.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/ee388f70ba0a481b. Report an issue: GitHub.