apache/iceberg · error · RuntimeException
Could not read object
Error message
Could not read object
What it means
deserializeFromBytes throws a plain RuntimeException with this (trailing-space) message when ObjectInputStream.readObject cannot resolve a class on the classpath (ClassNotFoundException). It means the serialized stream is structurally valid but references a class that is not available to the deserializing JVM.
Solutions
- Add the jar/module containing the serialized class to the deserializing classpath
- Confirm the class's package and serialVersionUID match on both sides (fix serialVersionUID or re-serialize)
- Regenerate the payload with the current code instead of deserializing legacy bytes
- Read the chained ClassNotFoundException cause to identify the exact missing class name
Example fix
// before T obj = SerializationUtil.deserializeFromBytes(storedBytes); // CNFE on legacy class // after MyDto dto = readJson(storedBytes); // prefer a stable format T obj = convert(dto);
Defensive patterns
Strategy: try-catch
Validate before calling
try {
Class.forName(payloadClassName, false, getClass().getClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException("payload class missing from classpath: " + payloadClassName);
} Try / catch
try {
T obj = SerializationUtil.deserializeFromBytes(bytes);
} catch (RuntimeException e) {
if (e.getCause() instanceof ClassNotFoundException) {
throw new IllegalStateException("missing class: " + e.getCause().getMessage(), e);
}
throw e;
} Prevention
- Ensure both producer and consumer ship the payload classes
- Pin serialVersionUID for serialized classes
- Prefer JSON/Avro over Java serialization across services
- Read e.getCause() to identify the exact missing class
When it happens
Trigger: Deserializing bytes whose payload class was written by a different classloader/application, the class was removed or renamed across versions, or the deserializing process lacks the module/jar containing the serialized type.
Common situations: Shipping payloads between services where only one has the concrete class; upgrading Iceberg or application code so an old stored serialized object references a deleted class; fat-jar shading changing package names.
Related errors
- Could not deserialize the WriteResult object
- Could not deserialize the WriteResult object
- Could not deserialize the WriteResult object
- Failed to deserialize the split.
- Failed to deserialize the split.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/be2ecc95237c1f1f.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/util/SerializationUtil.java:84
return baos.toByteArray();
} catch (IOException e) {
throw new UncheckedIOException("Failed to serialize object", e);
}
}
@SuppressWarnings({"DangerousJavaDeserialization", "unchecked"})
public static <T> T deserializeFromBytes(byte[] bytes) {
if (bytes == null) {
return null;
}
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais)) {
return (T) ois.readObject();
} catch (IOException e) {
throw new UncheckedIOException("Failed to deserialize object", e);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Could not read object ", e);
}
}
public static String serializeToBase64(Object obj) {
byte[] bytes = serializeToBytes(obj);
return new String(Base64.getMimeEncoder().encode(bytes), StandardCharsets.UTF_8);
}
public static <T> T deserializeFromBase64(String base64) {
if (base64 == null) {
return null;
}
byte[] bytes = Base64.getMimeDecoder().decode(base64.getBytes(StandardCharsets.UTF_8));
return deserializeFromBytes(bytes);
}
}
View on GitHub (pinned to 86d9c8fc54)