apache/flink · error · JsonParseException

Fail to deserialize at field: %s.

Error message

Fail to deserialize at field: %s.

What it means

Thrown by the ROW converter in JsonToRowDataConverters when any per-field converter throws while converting one field of a JSON object. It is a wrapper: the message names the field, and the cause carries the real conversion failure (type mismatch, bad numeric/date literal, variant/bytes failure, etc.). Fixing it means fixing the nested cause for the named field.

Source

Thrown at flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/JsonToRowDataConverters.java:365

        final JsonToRowDataConverter[] fieldConverters =
                rowType.getFields().stream()
                        .map(RowType.RowField::getType)
                        .map(this::createConverter)
                        .toArray(JsonToRowDataConverter[]::new);
        final String[] fieldNames = rowType.getFieldNames().toArray(new String[0]);

        return jsonNode -> {
            ObjectNode node = (ObjectNode) jsonNode;
            int arity = fieldNames.length;
            GenericRowData row = new GenericRowData(arity);
            for (int i = 0; i < arity; i++) {
                String fieldName = fieldNames[i];
                JsonNode field = node.get(fieldName);
                try {
                    Object convertedField = convertField(fieldConverters[i], fieldName, field);
                    row.setField(i, convertedField);
                } catch (Throwable t) {
                    throw new JsonParseException(
                            String.format("Fail to deserialize at field: %s.", fieldName), t);
                }
            }
            return row;
        };
    }

    private Object convertField(
            JsonToRowDataConverter fieldConverter, String fieldName, JsonNode field) {
        if (field == null) {
            if (failOnMissingField) {
                throw new JsonParseException("Could not find field with name '" + fieldName + "'.");
            } else {
                return null;
            }
        } else {
            return fieldConverter.convert(field);
        }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Read the cause chain of the JsonParseException to identify the underlying failure for the named field
  2. Check the field's JSON value in the failing record against the declared Flink type and correct the DDL or the data
  3. For date/time fields, verify the value matches the ISO-8601 formats Flink expects (or configure a custom format if supported by the pipeline)
  4. If bad records are expected and skippable, set the format's ignore-parse-errors option where available (Canal/Debezium variants) or filter/quarantine upstream

Example fix

// before: JSON {"ts": "2024-13-45 99:00:00"} against TIMESTAMP(3)
// after: fix upstream to emit "2024-01-05 10:00:00" or declare the column STRING and parse leniently in a UDF
Defensive patterns

Strategy: try-catch

Try / catch

catch (JsonParseException e) — read getFieldName from message and unwrap getCause(); fix the inner conversion (type mismatch / format) rather than retrying the same record.

Prevention

When it happens

Trigger: Any field-level conversion error inside a ROW: a JSON string where a number is expected, an invalid TIMESTAMP/DATE format, a failed VARIANT or BINARY conversion (see 1400/1401), a DECIMAL with more digits than precision, etc. The wrapped converters run per record, so this appears at runtime on the offending message.

Common situations: Upstream schema drift (a field flips from number to string); malformed date/timestamp strings; nulls represented as "" instead of JSON null; precision/scale mismatches on DECIMAL columns.

Related errors


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