{"record":{"id":"c6302f57a8754998","repo":"apache/flink","slug":"unable-to-serialize-variant-value","errorCode":null,"errorMessage":"Unable to serialize VARIANT value.","messagePattern":"Unable to serialize VARIANT value\\.","errorType":"exception","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/RowDataToJsonConverters.java","lineNumber":177,"sourceCode":"        }\n    }\n\n    private RowDataToJsonConverter createDecimalConverter() {\n        return (mapper, reuse, value) -> {\n            BigDecimal bd = ((DecimalData) value).toBigDecimal();\n            return mapper.getNodeFactory()\n                    .numberNode(\n                            mapper.isEnabled(WRITE_BIGDECIMAL_AS_PLAIN)\n                                    ? bd\n                                    : bd.stripTrailingZeros());\n        };\n    }\n\n    private JsonNode convertVariant(ObjectMapper mapper, JsonNode reuse, Object value) {\n        try {\n            return mapper.readTree(((Variant) value).toJson());\n        } catch (IOException e) {\n            throw new JsonParseException(\"Unable to serialize VARIANT value.\", e);\n        }\n    }\n\n    private RowDataToJsonConverter createDateConverter() {\n        return (mapper, reuse, value) -> {\n            int days = (int) value;\n            LocalDate date = LocalDate.ofEpochDay(days);\n            return mapper.getNodeFactory().textNode(ISO_LOCAL_DATE.format(date));\n        };\n    }\n\n    private RowDataToJsonConverter createTimeConverter() {\n        return (mapper, reuse, value) -> {\n            int millisecond = (int) value;\n            LocalTime time = LocalTime.ofNanoOfDay(millisecond * 1000_000L);\n            return mapper.getNodeFactory().textNode(SQL_TIME_FORMAT.format(time));\n        };\n    }","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/RowDataToJsonConverters.java#L159-L195","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the VARIANT value is produced by the same Flink version's VARIANT tooling (BinaryVariantInternalBuilder) rather than raw bytes","Re-derive the variant from its original JSON instead of restoring/passing opaque binary variants across versions","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","Check for version mismatches between the producing job/format and the consuming JSON sink, and align them"],"exampleFix":"// before: variant built from opaque bytes\nbyte[] raw = ...; BinaryVariant v = BinaryVariant.fromBytes(raw);\n\n// after: build from JSON so toJson() is guaranteed parseable\nBinaryVariant v = BinaryVariantInternalBuilder.parseJson(jsonText, false);","handlingStrategy":"validation","validationCode":"String json = ((Variant) value).toJson();\ntry { mapper.readTree(json); } catch (IOException e) { /* do not write this variant to JSON sink; quarantine */ }","typeGuard":null,"tryCatchPattern":"catch (JsonParseException e) for 'Unable to serialize VARIANT' — treat as data corruption; drop or quarantine the record, never a silent fallback.","preventionTips":["Build variants only via BinaryVariantInternalBuilder","Do not restore opaque variant bytes across Flink versions","Unit-test variant round-trips (toJson/readTree) on representative data"],"tags":["json","variant","serialization","version-mismatch"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}