hibernate/hibernate-orm · error · IllegalStateException

Blobs may not be accessed after serialization

Error message

Blobs may not be accessed after serialization

What it means

SerializableBlobProxy adds java.io.Serializable to a Blob via a JDK dynamic proxy, but the wrapped Blob field is declared transient: only the proxy shell survives Java serialization. After a serialization round trip the field is null, so getWrappedBlob() - and therefore every Blob method routed through invoke() - throws IllegalStateException("Blobs may not be accessed after serialization"). The underlying bytes were never part of the serial form.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/SerializableBlobProxy.java:47

	/**
	 * Builds a serializable {@link Blob} wrapper around the given {@link Blob}.
	 *
	 * @param blob The {@link Blob} to be wrapped.
	 * @see #generateProxy(Blob)
	 */
	private SerializableBlobProxy(Blob blob) {
		this.blob = blob;
	}

	/**
	 * Access to the wrapped Blob reference
	 *
	 * @return The wrapped Blob reference
	 */
	public Blob getWrappedBlob() {
		if ( blob == null ) {
			throw new IllegalStateException( "Blobs may not be accessed after serialization" );
		}
		else {
			return blob;
		}
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if ( "getWrappedBlob".equals( method.getName() ) ) {
			return getWrappedBlob();
		}
		try {
			return method.invoke( getWrappedBlob(), args );
		}
		catch ( AbstractMethodError e ) {
			throw new HibernateException( "The JDBC driver does not implement the method: " + method, e );
		}
		catch ( InvocationTargetException e ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Map the attribute as byte[] instead of Blob so the raw data itself is serialized
  2. Do not carry the entity across serialization - reload it by id in the new session/transaction
  3. If you must serialize, extract first (blob.getBytes(1, (int) blob.length())) and rebuild with Hibernate.getLobHelper().createBlob(bytes)
  4. Keep Hibernate-managed LOBs inside the owning session's lifetime only

Example fix

// before
@Entity class Doc { @Lob Blob content; }   // proxied Blob stored in HttpSession ->
 session.setAttribute("doc", doc);            // after failover: IllegalStateException

// after
@Entity class Doc {
    @Lob byte[] content;   // plain serializable data; set via blob.getBytes(1, (int) blob.length())
}
Defensive patterns

Strategy: validation

Validate before calling

// Run BEFORE serializing anything that might hold a Hibernate Blob proxy
static byte[] detachBlob(java.sql.Blob blob) throws SQLException {
    try {
        return blob.getBytes(1, (int) blob.length()); // works on the live proxy
    } catch (IllegalStateException e) {
        throw new IllegalStateException(
            "Blob already deserialized/empty - reload the entity in this session", e);
    }
}
// store detachBlob(blob) in the session/cache instead of the proxy

Try / catch

try {
    byte[] data = blob.getBytes(1, (int) blob.length());
} catch (IllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().contains("after serialization")) {
        // the lob is gone: the only correct recovery is re-fetching the row
        entity = session.find(Entity.class, id);
        data = entity.getContent();
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Storing a Hibernate-proxied Blob in an HttpSession that gets passivated/replicated (Spring Session, cluster failover); putting a detached entity containing the proxy into a store-by-value cache (ehcache/Infinispan in that mode); RMI or Java-serialization of the entity; calling ((WrappedBlob) proxy).getWrappedBlob() after deserialization.

Common situations: Web apps saving Hibernate entities with Blob fields in the HTTP session across clustered nodes; serializing detached entities into queues or distributed caches; JSF view state holding entities; any architecture that ships entities between JVMs via Java serialization.

Related errors


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