hibernate/hibernate-orm · error · SerializationException
could not deserialize
Error message
could not deserialize
What it means
Deserialization wraps CustomObjectInputStream.readObject failures: ClassNotFoundException (the stream references a class invisible to the supplied and fallback classloaders) and IOException subtypes (StreamCorruptedException for bytes that are not a Java serialization stream, InvalidClassException for serialVersionUID/version drift, truncated input). All become SerializationException with this message; the precise reason is on the cause chain.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/util/SerializationHelper.java:205
}
public static <T> T doDeserialize(
InputStream inputStream,
ClassLoader loader,
ClassLoader fallbackLoader1,
ClassLoader fallbackLoader2) throws SerializationException {
if ( inputStream == null ) {
throw new IllegalArgumentException( "The InputStream must not be null" );
}
CORE_LOGGER.trace( "Starting deserialization of object" );
try ( var in = new CustomObjectInputStream( inputStream, loader, fallbackLoader1, fallbackLoader2 ) ) {
//noinspection unchecked
return (T) in.readObject();
}
catch (ClassNotFoundException | IOException e) {
throw new SerializationException( "could not deserialize", e );
}
}
/**
* Deserializes an object from an array of bytes using the
* Thread Context ClassLoader (TCCL). If there is no TCCL set,
* the classloader of the calling class is used.
* <p>
* Delegates to {@link #deserialize(byte[], ClassLoader)}
*
* @param objectData the serialized object, must not be null
*
* @return the deserialized object
*
* @throws IllegalArgumentException if <code>objectData</code> is <code>null</code>
* @throws SerializationException (runtime) if the serialization fails
*/
public static Object deserialize(byte[] objectData) throws SerializationException {View on GitHub (pinned to fad1729dce)
Solutions
- Inspect the cause: ClassNotFoundException -> make the class visible to the reading classloader or pass the right loader explicitly (e.g., Thread.currentThread().getContextClassLoader()); InvalidClassException -> restore/align serialVersionUID or rewrite the stored data; StreamCorruptedException -> the input is not a Java serialization stream, fix the producer or format.
- Declare a fixed private static final long serialVersionUID on every class persisted in serialized form.
- When classes or packages move, migrate stored blobs: read with the old mapping, write with the new.
Example fix
// before Object o = SerializationHelper.deserialize(blobBytes, Helper.class.getClassLoader()); // redeploy -> ClassNotFoundException -> "could not deserialize" // after ClassLoader tccl = Thread.currentThread().getContextClassLoader(); Object o = SerializationHelper.deserialize(blobBytes, tccl);
Defensive patterns
Strategy: try-catch
Validate before calling
static boolean looksLikeJavaSerialization(byte[] data) {
return data != null && data.length >= 4
&& (data[0] & 0xFF) == 0xAC && (data[1] & 0xFF) == 0xED && data[2] == 0 && data[3] == 5;
} Try / catch
try {
Object o = SerializationHelper.deserialize(blobBytes, Thread.currentThread().getContextClassLoader());
} catch (org.hibernate.type.SerializationException e) {
Throwable cause = e.getCause();
if (cause instanceof ClassNotFoundException) { /* classloader/class visibility fix */ }
else if (cause instanceof java.io.InvalidClassException) { /* serialVersionUID drift; re-export data */ }
else if (cause instanceof java.io.StreamCorruptedException) { /* bytes are not a Java serialization stream */ }
} Prevention
- Declare explicit serialVersionUID on every class persisted in serialized form.
- Pass the application classloader (often the TCCL) explicitly when deserializing.
- Version stored serialized blobs; plan a migration step whenever classes move or rename.
When it happens
Trigger: deserialize()/doDeserialize on bytes not produced by Java serialization; entity classes renamed, moved, or loaded by a different classloader than the one used to write the blob; serialVersionUID changed between write and read; byte arrays truncated or sliced at the wrong offset.
Common situations: Serialized LOB columns read after refactoring package names; app-server redeploys where the writing classloader differs from the reading one; data written by another serializer (JSON, Kryo) passed to the Java deserializer; blobs extracted with wrong offsets from a composite payload.
Related errors
- No SessionFactory with uuid [{uuid}] and name [{name}]
- Could not find a SessionFactory [uuid={},name={}]
- Unable to check validity of passed ValidatorFactory
- Could not locate method needed for ValidatorFactory validati
- Could not locate TypeSafeActivator class
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/3b2c35f75e1b525c.
Report an issue: GitHub.