apache/iceberg · error · UncheckedIOException
Fail to serialize data statistics
Error message
Fail to serialize data statistics
What it means
StatisticsUtil.serializeDataStatistics wraps any IOException thrown while serializing a DataStatistics object (used in Flink key shuffle downsketching) into an UncheckedIOException. This is an internal failure of the Flink TypeSerializer for the DataStatistics type; the library throws it because serialization failures cannot propagate as checked IOExceptions through non-declaring call sites.
Solutions
- Verify the TypeSerializer<DataStatistics> passed in matches the DataStatistics implementation currently in use (SketchDataStatistics vs MapDataStatistics) and its version.
- Check for Flink/Iceberg version mismatch between job manager and task manager classpaths; align all nodes to the same iceberg-flink-runtime version.
- Reproduce the wrapped cause via e.getCause() to see the underlying IOException and fix the serializer accordingly.
- If a job restore triggered it, restart the job without state or migrate state with a matching serializer version.
Example fix
// before
byte[] bytes = StatisticsUtil.serializeDataStatistics(stats, wrongSerializer);
// after
TypeSerializer<DataStatistics> serializer =
new DataStatisticsSerializer(); // matches DataStatistics impl and version
byte[] bytes = StatisticsUtil.serializeDataStatistics(stats, serializer); Defensive patterns
Strategy: try-catch
Validate before calling
if (dataStatistics == null) throw new IllegalArgumentException("dataStatistics must not be null");
// ensure serializer type matches the DataStatistics impl before calling
Preconditions.checkArgument(serializer instanceof DataStatisticsSerializer); Type guard
boolean isCompatible(TypeSerializer<DataStatistics> s, DataStatistics d) {
return s != null && d != null;
} Try / catch
try {
byte[] bytes = StatisticsUtil.serializeDataStatistics(stats, serializer);
} catch (UncheckedIOException e) {
IOException cause = e.getCause();
LOG.error("statistics serialization failed", cause);
throw e; // or fall back to empty statistics
} Prevention
- Pin the same iceberg-flink-runtime version on all task/job managers.
- Only use serializers obtained from the matching DataStatistics type.
- Log e.getCause() to diagnose serializer version drift early.
When it happens
Trigger: Calling StatisticsUtil.serializeDataStatistics(dataStatistics, serializer) when the provided TypeSerializer<DataStatistics> throws IOException during serialize(), e.g. because the serializer's internal buffer cannot grow or the object graph is inconsistent with the serializer version.
Common situations: Job upgrade/downgrade where the serialized statistics type no longer matches the serializer handed to the utility; a custom or misregistered TypeSerializer that fails mid-serialization; JVM heap/buffer issues during state transfer in the shuffle.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- Fail to serialize aggregated statistics
- Fail to deserialize data statistics
- Fail to deserialize data statistics
- Fail to serialize aggregated statistics
- Fail to serialize aggregated statistics
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/0ad3c4f403b95d4d.
Report an issue: GitHub.
Appendix: source
Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/sink/shuffle/StatisticsUtil.java:49
static DataStatistics createTaskStatistics(
StatisticsType type, int operatorParallelism, int numPartitions) {
if (type == StatisticsType.Map) {
return new MapDataStatistics();
} else {
return new SketchDataStatistics(
SketchUtil.determineOperatorReservoirSize(operatorParallelism, numPartitions));
}
}
static byte[] serializeDataStatistics(
DataStatistics dataStatistics, TypeSerializer<DataStatistics> statisticsSerializer) {
DataOutputSerializer out = new DataOutputSerializer(64);
try {
statisticsSerializer.serialize(dataStatistics, out);
return out.getCopyOfBuffer();
} catch (IOException e) {
throw new UncheckedIOException("Fail to serialize data statistics", e);
}
}
static DataStatistics deserializeDataStatistics(
byte[] bytes, TypeSerializer<DataStatistics> statisticsSerializer) {
DataInputDeserializer input = new DataInputDeserializer(bytes, 0, bytes.length);
try {
return statisticsSerializer.deserialize(input);
} catch (IOException e) {
throw new UncheckedIOException("Fail to deserialize data statistics", e);
}
}
static byte[] serializeCompletedStatistics(
CompletedStatistics completedStatistics,
TypeSerializer<CompletedStatistics> statisticsSerializer) {
try {
DataOutputSerializer out = new DataOutputSerializer(1024);View on GitHub (pinned to 86d9c8fc54)