apache/flink · error · JsonParseException

Unable to serialize VARIANT value.

Error message

Unable to serialize VARIANT value.

What it means

Thrown by RowDataToJsonConverters.convertVariant when ObjectMapper.readTree fails to re-parse the JSON text produced by Variant.toJson() for a VARIANT value being written to JSON. The variant's textual form should be valid JSON, so an IOException here means the variant object could not render parseable JSON — typically a malformed or corrupted BinaryVariant instance.

Source

Thrown at flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/RowDataToJsonConverters.java:177

        }
    }

    private RowDataToJsonConverter createDecimalConverter() {
        return (mapper, reuse, value) -> {
            BigDecimal bd = ((DecimalData) value).toBigDecimal();
            return mapper.getNodeFactory()
                    .numberNode(
                            mapper.isEnabled(WRITE_BIGDECIMAL_AS_PLAIN)
                                    ? bd
                                    : bd.stripTrailingZeros());
        };
    }

    private JsonNode convertVariant(ObjectMapper mapper, JsonNode reuse, Object value) {
        try {
            return mapper.readTree(((Variant) value).toJson());
        } catch (IOException e) {
            throw new JsonParseException("Unable to serialize VARIANT value.", e);
        }
    }

    private RowDataToJsonConverter createDateConverter() {
        return (mapper, reuse, value) -> {
            int days = (int) value;
            LocalDate date = LocalDate.ofEpochDay(days);
            return mapper.getNodeFactory().textNode(ISO_LOCAL_DATE.format(date));
        };
    }

    private RowDataToJsonConverter createTimeConverter() {
        return (mapper, reuse, value) -> {
            int millisecond = (int) value;
            LocalTime time = LocalTime.ofNanoOfDay(millisecond * 1000_000L);
            return mapper.getNodeFactory().textNode(SQL_TIME_FORMAT.format(time));
        };
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Verify the VARIANT value is produced by the same Flink version's VARIANT tooling (BinaryVariantInternalBuilder) rather than raw bytes
  2. Re-derive the variant from its original JSON instead of restoring/passing opaque binary variants across versions
  3. If writing the raw variant is the goal, serialize the column as the variant's JSON text (STRING) via toJson() in a UDF and write that
  4. Check for version mismatches between the producing job/format and the consuming JSON sink, and align them

Example fix

// before: variant built from opaque bytes
byte[] raw = ...; BinaryVariant v = BinaryVariant.fromBytes(raw);

// after: build from JSON so toJson() is guaranteed parseable
BinaryVariant v = BinaryVariantInternalBuilder.parseJson(jsonText, false);
Defensive patterns

Strategy: validation

Validate before calling

String json = ((Variant) value).toJson();
try { mapper.readTree(json); } catch (IOException e) { /* do not write this variant to JSON sink; quarantine */ }

Try / catch

catch (JsonParseException e) for 'Unable to serialize VARIANT' — treat as data corruption; drop or quarantine the record, never a silent fallback.

Prevention

When it happens

Trigger: Serializing a RowData with a VARIANT column through the 'json' format where the Variant value is malformed (constructed from corrupted bytes, an incompatible binary layout, or an invalid internal build), causing Variant.toJson() to emit something readTree rejects.

Common situations: VARIANT data produced by a different Flink/table version with a changed binary layout; hand-constructed BinaryVariant from raw bytes; corrupted state after a checkpoint restore across versions; bugs in variant-building code paths.

Related errors


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