hibernate/hibernate-orm · error · HibernateException
Unable to access lob stream
Error message
Unable to access lob stream
What it means
PrimitiveByteArrayJavaType.wrapOrNull() converts an incoming java.sql.Blob into byte[] by calling getBinaryStream() and fully reading it; any SQLException from the driver (invalidated locator, stream already consumed, connection closed, LOB freed) is wrapped as HibernateException("Unable to access lob stream"). Like the NClob variant, this almost always means the Blob handle outlived the transaction or connection that owned it.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/PrimitiveByteArrayJavaType.java:159
if ( wrapped == null ) {
throw unknownWrap( value.getClass() );
}
return wrapped;
}
private <X> @Nullable byte[] wrapOrNull(@Nonnull X value) {
if (value instanceof byte[] bytes) {
return bytes;
}
if (value instanceof InputStream inputStream) {
return DataHelper.extractBytes( inputStream );
}
if ( value instanceof Blob blob ) {
try {
return DataHelper.extractBytes( blob.getBinaryStream() );
}
catch ( SQLException e ) {
throw new HibernateException( "Unable to access lob stream", e );
}
}
else if ( value instanceof Byte byteValue ) {
// Support binding a single element as parameter value
return new byte[]{ byteValue };
}
else if ( value instanceof Byte[] array ) {
final byte[] bytes = new byte[array.length];
for ( int i = 0; i < array.length; i++ ) {
bytes[i] = array[i];
}
return bytes;
}
return null;
}
@Override
public @Nullable byte[] coerce(@Nullable Object value) {View on GitHub (pinned to fad1729dce)
Solutions
- Materialize byte[] content while the session and transaction are open (eager fetch or explicit read in service code)
- Keep the session open until the content is read, or refresh the entity inside a new transaction before accessing the field
- Avoid holding live java.sql.Blob handles across requests - copy to byte[] immediately after load
- Check driver settings/docs regarding temporary LOB lifetime at commit (Oracle temp LOBs)
Example fix
// before
Attachment a = repo.findById(id).get(); // session closes after tx
byte[] data = a.getData(); // lazy Blob wrap after close -> HibernateException
// after
@Transactional(readOnly = true)
byte[] loadNow(Long id) {
return repo.findById(id).map(Attachment::getData).orElseThrow(); // read inside tx
}
// or map the column directly as byte[] with eager materialization Defensive patterns
Strategy: try-catch
Validate before calling
static byte[] materializeInTx(jakarta.persistence.EntityManager em, Long id) {
return em.executeInTransaction(() -> {
Attachment a = em.find(Attachment.class, id);
return a == null ? null : a.getData(); // Blob -> byte[] while locator is live
});
} Type guard
static boolean isUsable(java.sql.Blob b) {
try { b.length(); return true; } catch (java.sql.SQLException e) { return false; }
} Try / catch
try {
return attachment.getData();
} catch (HibernateException e) {
if ("Unable to access lob stream".equals(e.getMessage()) && e.getCause() instanceof java.sql.SQLException) {
return reloadInsideTransaction(attachment.getId()); // fresh locator, not a blind retry
}
throw e;
} Prevention
- Materialize byte[] from Blob inside the transaction that loaded the entity
- Do not detach/serialize entities holding live Blob handles
- Read LOB streams exactly once; copy content if multiple consumers need it
When it happens
Trigger: A byte[] attribute mapped from a BLOB column is lazily materialized after the session/transaction closed; the Blob stream is read twice or partially consumed elsewhere; drivers (Oracle, DB2) that auto-release temporary LOBs at commit
Common situations: Lazy-loaded attachments read in a view layer after the transaction ended; entities serialized/deserialized across requests with live Blob handles; background jobs processing entities after their session ended
Related errors
- Unable to access nclob stream
- Property '<propertyName>' may not be annotated '@BatchSize'
- Cannot lazily initialize collection
- Cannot lazily initialize collection (collection is being rem
- force initializing collection loading
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/46b847938af8d38d.
Report an issue: GitHub.