apache/iceberg · critical · IOException
Could not deserialize the WriteResult object
Error message
Could not deserialize the WriteResult object
What it means
WriteResultSerializer.deserialize reads the serialized WriteResult bytes and calls InstantiationUtil.deserializeObject. If deserialization fails with ClassNotFoundException (the WriteResult class or its dependencies are missing from the classloader), it is wrapped in an IOException with this message.
Solutions
- Ensure the same Iceberg Flink runtime jar is on every TaskManager's classpath (not only the client).
- Set classloader.check-leaked-classloader and consider classloader.parent-first patterns for org.apache.iceberg packages.
- If resuming from a savepoint across Iceberg upgrades, verify checkpointed committables are compatible or discard pending committables.
- Re-run with the identical Iceberg version used when the data was serialized.
Example fix
// before: runtime jar added only to client // after flink run -C file:///jars/iceberg-flink-runtime.jar ... # ship to all TMs via ./lib
Defensive patterns
Strategy: try-catch
Validate before calling
// Before submitting, verify the runtime jar is deployed:
assert Class.forName("org.apache.iceberg.flink.sink.WriteResult", true,
Thread.currentThread().getContextClassLoader()) != null; Try / catch
try {
WriteResult r = serializer.deserialize(version, bytes);
} catch (IOException e) {
if (e.getCause() instanceof ClassNotFoundException) {
LOG.error("Iceberg classes missing from task classloader; check TM classpath", e);
}
throw e;
} Prevention
- Place iceberg-flink-runtime jar in Flink lib/ or ship it to every TaskManager.
- Use the same Iceberg version on client and cluster.
- Avoid classloader isolation gaps for org.apache.iceberg packages.
When it happens
Trigger: Deserializing a WriteResult committable whose payload requires classes not present in the task's classloader — typically when user classloading is enabled (child-first) and Iceberg classes live in a plugin/user classloader not visible to the deserializing operator.
Common situations: Flink classloading isolation between job stages; upgrading Iceberg across a restart with old checkpoints containing committables; missing iceberg-flink runtime jar on some TaskManagers.
Related errors
- An error occurred reloading table
- An error occurred reloading table
- Could not deserialize the WriteResult object
- Could not deserialize the WriteResult object
- Could not deserialize the WriteResult object
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/b9f380e7e79c8d22.
Report an issue: GitHub.
Appendix: source
Thrown at flink/v2.1/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)