apache/iceberg · critical · IOException
Could not deserialize the WriteResult object
Error message
Could not deserialize the WriteResult object
What it means
WriteResultSerializer.deserialize wraps ClassNotFoundException from InstantiationUtil.deserializeObject into this IOException. The WriteResult bytes are valid enough to read, but the WriteResult class (or a nested class) cannot be loaded in the current JVM — a classpath/version mismatch when restoring state.
Source
Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/sink/WriteResultSerializer.java:58
public byte[] serialize(WriteResult writeResult) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputViewStreamWrapper view = new DataOutputViewStreamWrapper(out);
byte[] result = InstantiationUtil.serializeObject(writeResult);
view.write(result);
return out.toByteArray();
}
@Override
public WriteResult deserialize(int version, byte[] serialized) throws IOException {
if (version == 1) {
DataInputDeserializer view = new DataInputDeserializer(serialized);
byte[] resultBuf = new byte[serialized.length];
view.read(resultBuf);
try {
return InstantiationUtil.deserializeObject(
resultBuf, IcebergCommittableSerializer.class.getClassLoader());
} catch (ClassNotFoundException cnc) {
throw new IOException("Could not deserialize the WriteResult object", cnc);
}
}
throw new IOException("Unrecognized version or corrupt state: " + version);
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Ensure the exact iceberg-flink-runtime version that wrote the state is on the classpath of JobManager and TaskManagers.
- Fix shading conflicts: mark Iceberg dependencies provided in the job jar so the cluster's version is used consistently.
- Resume from a savepoint produced by the current version (stop-with-savepoint --drain) instead of old state.
- If using Flink's classloader options, set classloader.check-leaked-classloader / child-first consistently across versions.
Example fix
// before (pom.xml) <dependency>org.apache.iceberg:iceberg-flink-runtime-1.19:compile</dependency> // after <dependency> <groupId>org.apache.iceberg</groupId> <artifactId>iceberg-flink-runtime-1.19</artifactId> <scope>provided</scope> </dependency>
Defensive patterns
Strategy: type-guard
Validate before calling
// verify WriteResult is loadable on the cluster classpath before resuming
try {
Class.forName("org.apache.iceberg.flink.sink.WriteResult");
} catch (ClassNotFoundException e) {
throw new IllegalStateException("iceberg-flink runtime jar missing from classpath", e);
} Type guard
static boolean writeResultLoadable() {
try {
WriteResultSerializer.class.getClassLoader().loadClass("org.apache.iceberg.flink.sink.WriteResult");
return true;
} catch (ClassNotFoundException e) {
return false;
}
} Try / catch
try {
env.execute();
} catch (Exception e) {
Throwable root = ExceptionUtils.findThrowable(e, ClassNotFoundException.class).orElse(null);
if (root != null && root.getName().contains("WriteResult")) {
// fix runtime jar/shading, then resubmit
}
throw e;
} Prevention
- Mark Iceberg dependencies as provided so job and cluster use one version.
- Deploy the exact iceberg-flink-runtime jar the state was written with.
- Test savepoint restore in staging after every version bump.
When it happens
Trigger: Restoring a Flink checkpoint/savepoint whose WriteResult state was written with a different Iceberg version whose WriteResult class isn't loadable (missing iceberg-flink-runtime jar on TaskManagers, shaded duplicate classes, or version downgrade).
Common situations: Job jar shading Iceberg differently than the runtime; TaskManager classpath missing the iceberg jars after a cluster upgrade; resuming state across incompatible Iceberg releases.
Related errors
- Failed to deserialize the split.
- Unrecognized version or corrupt state: <version>
- Unknown serialize version: ${version}
- Unrecognized version or corrupt state: ${version}
- Could not deserialize the WriteResult object
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/1c2b5449667a001f.
Report an issue: GitHub.