{"record":{"id":"def7223348d3dac5","repo":"apache/iceberg","slug":"unsupported-data-statistics-type","errorCode":null,"errorMessage":"Unsupported data statistics type: ","messagePattern":"Unsupported data statistics type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/sink/shuffle/DataStatisticsSerializer.java","lineNumber":91,"sourceCode":"  public DataStatistics copy(DataStatistics obj) {\n    StatisticsType statisticsType = obj.type();\n    if (statisticsType == StatisticsType.Map) {\n      MapDataStatistics from = (MapDataStatistics) obj;\n      Map<SortKey, Long> fromStats = (Map<SortKey, Long>) from.result();\n      Map<SortKey, Long> toStats = Maps.newHashMap(fromStats);\n      return new MapDataStatistics(toStats);\n    } else if (statisticsType == StatisticsType.Sketch) {\n      // because ReservoirItemsSketch doesn't expose enough public methods for cloning,\n      // this implementation adopted the less efficient serialization and deserialization.\n      SketchDataStatistics from = (SketchDataStatistics) obj;\n      ReservoirItemsSketch<SortKey> fromStats = (ReservoirItemsSketch<SortKey>) from.result();\n      byte[] bytes = fromStats.toByteArray(sketchSerializer);\n      Memory memory = Memory.wrap(bytes);\n      ReservoirItemsSketch<SortKey> toStats =\n          ReservoirItemsSketch.heapify(memory, sketchSerializer);\n      return new SketchDataStatistics(toStats);\n    } else {\n      throw new IllegalArgumentException(\"Unsupported data statistics type: \" + statisticsType);\n    }\n  }\n\n  @Override\n  public DataStatistics copy(DataStatistics from, DataStatistics reuse) {\n    // not much benefit to reuse\n    return copy(from);\n  }\n\n  @Override\n  public int getLength() {\n    return -1;\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  @Override\n  public void serialize(DataStatistics obj, DataOutputView target) throws IOException {\n    StatisticsType statisticsType = obj.type();","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/sink/shuffle/DataStatisticsSerializer.java#L73-L109","documentation":"DataStatisticsSerializer.copy() deserializes statistics whose type was read from the wire (via statisticsTypeSerializer) and reconstructs either a MapDataStatistics or SketchDataStatistics. If the recorded StatisticsType is neither Map nor Sketch, the serializer cannot reconstruct the object and throws IllegalArgumentException. This guards against corrupted serialization output or a StatisticsType enum that the current code version does not handle.","triggerScenarios":"Calling copy(DataStatistics, DataStatistics) on a DataStatistics object whose type() returns a StatisticsType value other than Map or Sketch (e.g. NONE or an enum value from a newer Iceberg version). The type is serialized/deserialized through DataStatisticsSerializer.serialize/deserialize before reaching copy's branch logic.","commonSituations":"Running a job where checkpoints/state were written by a newer Iceberg version that introduced a new StatisticsType; manually constructing a DataStatistics wrapper with an unexpected type; bugs in custom DataStatistics implementations whose type() lies about the concrete class.","solutions":["Align the Iceberg flink runtime version between job submission and the cluster/checkpoint state so StatisticsType values match.","Discard old incompatible state (e.g. start with a fresh savepoint / allowNonRestoredState) if it contains unknown statistics types.","If you maintain a fork, add a branch handling the new StatisticsType in copy() (and serialize/deserialize) of DataStatisticsSerializer."],"exampleFix":"// before: pass through unknown statistics\nDataStatistics copied = serializer.copy(stats, null);\n// after: guard before copy\nif (stats.type() == StatisticsType.Map || stats.type() == StatisticsType.Sketch) {\n  DataStatistics copied = serializer.copy(stats, null);\n} else {\n  DataStatistics copied = new MapDataStatistics(Collections.emptyMap());\n}","handlingStrategy":"type-guard","validationCode":"if (stats.type() != StatisticsType.Map && stats.type() != StatisticsType.Sketch) {\n  throw new IllegalStateException(\"Cannot copy statistics of type \" + stats.type());\n}","typeGuard":"boolean copyable(DataStatistics s) {\n  return s.type() == StatisticsType.Map || s.type() == StatisticsType.Sketch;\n}","tryCatchPattern":"try {\n  copied = serializer.copy(stats, null);\n} catch (IllegalArgumentException e) {\n  LOG.warn(\"Unsupported statistics type {}, using empty stats\", stats.type(), e);\n  copied = new MapDataStatistics(Collections.emptyMap());\n}","preventionTips":["Pin a single Iceberg version across submission and cluster classpaths.","Never resume state written by a newer Iceberg release with an older runtime.","Only pass MapDataStatistics/SketchDataStatistics into serializer APIs."],"tags":["flink","serialization","data-statistics"],"backgroundTag":"unsupported-enum-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}