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

  1. 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.
  2. Declare a fixed private static final long serialVersionUID on every class persisted in serialized form.
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/3b2c35f75e1b525c. Report an issue: GitHub.