apache/iceberg · error · RuntimeException

Failed to deserialize the split.

Error message

Failed to deserialize the split.

What it means

IcebergSourceSplit.deserializeV1 uses Java serialization (InstantiationUtil.deserializeObject); if the class of the serialized object cannot be found on the classpath, it wraps ClassNotFoundException into RuntimeException. The split bytes reference classes unavailable at deserialization time.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/source/split/IcebergSourceSplit.java:131

                        .add("length", fileScanTask.length())
                        .toString())
            .collect(Collectors.toList()));
  }

  byte[] serializeV1() throws IOException {
    if (serializedBytesCache == null) {
      serializedBytesCache = InstantiationUtil.serializeObject(this);
    }

    return serializedBytesCache;
  }

  static IcebergSourceSplit deserializeV1(byte[] serialized) throws IOException {
    try {
      return InstantiationUtil.deserializeObject(
          serialized, IcebergSourceSplit.class.getClassLoader());
    } catch (ClassNotFoundException e) {
      throw new RuntimeException("Failed to deserialize the split.", e);
    }
  }

  byte[] serializeV2() throws IOException {
    return serialize(2);
  }

  byte[] serializeV3() throws IOException {
    return serialize(3);
  }

  private byte[] serialize(int version) throws IOException {
    if (serializedBytesCache == null) {
      DataOutputSerializer out = SERIALIZER_CACHE.get();
      Collection<FileScanTask> fileScanTasks = task.tasks();
      Preconditions.checkArgument(
          fileOffset >= 0 && fileOffset < fileScanTasks.size(),
          "Invalid file offset: %s. Should be within the range of [0, %s)",

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure the iceberg-flink runtime jar is on every TaskManager's classpath (or bundled in the user job jar, not both partially).
  2. Align connector versions between the job that created the checkpoint and the restoring job.
  3. Check for shade/relocation mismatches (org.apache.iceberg classes relocated differently between builds).
  4. Inspect the cause ClassNotFoundException for the exact missing class and add the dependency providing it.

Example fix

// before
# user jar contains iceberg classes shaded under different package than cluster lib
// after
# use consistent coordinates: bundle org.apache.iceberg:iceberg-flink-runtime same version in user jar only
Defensive patterns

Strategy: validation

Validate before calling

// Verify the split classes resolve on the restoring cluster before submitting
Class.forName("org.apache.iceberg.flink.source.split.IcebergSourceSplit");
Class.forName("org.apache.iceberg.SerializableTable");

Try / catch

try {
  split = IcebergSourceSplitSerializer.INSTANCE.deserialize(version, bytes);
} catch (RuntimeException e) {
  if (e.getCause() instanceof ClassNotFoundException) {
    throw new IllegalStateException("Iceberg classes missing on TaskManager classpath", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Restoring a checkpoint/savepoint or transferring split bytes where IcebergSourceSplit (or its referenced classes, e.g., the table/SerializableTable) is not on the TaskManager classpath, or was serialized by a different connector version with moved classes.

Common situations: Missing Iceberg jars on TaskManagers; shading conflicts relocating class packages; restoring state across connector versions with relocated classes.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/6b914879831b171c. Report an issue: GitHub.