hibernate/hibernate-orm · error · HibernateException
IOException occurred reading a binary value
Error message
IOException occurred reading a binary value
What it means
StreamBackedBinaryStream.getBytes() lazily materializes the wrapped InputStream with readAllBytes() the first time the byte[] is needed (e.g. when binding a stream-backed Blob to a statement). An IOException during that read is wrapped in HibernateException('IOException occurred reading a binary value').
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/StreamBackedBinaryStream.java:43
public StreamBackedBinaryStream(InputStream stream, long length) {
this.stream = stream;
this.length = length;
}
@Override
public InputStream getInputStream() {
return stream;
}
@Override
public byte[] getBytes() {
if ( bytes == null ) {
try {
bytes = stream.readAllBytes();
}
catch (IOException e) {
throw new HibernateException( "IOException occurred reading a binary value", e );
}
}
return bytes;
}
@Override
public long getLength() {
return length;
}
@Override
public Blob asBlob(LobCreator lobCreator) {
return lobCreator.createBlob( stream, length );
}
@Override
public void release() {
try {View on GitHub (pinned to fad1729dce)
Solutions
- Do not consume the InputStream before/after giving it to Hibernate; treat it as owned by Hibernate
- Read the bytes into a byte[] first and create the Blob from the array if the source cannot stay open until flush
- Keep the stream and its resource (file/connection) open until the transaction commits
Example fix
// before: stream may be closed by the time Hibernate reads it entity.setAttachment(lobHelper.createBlob(socketStream, len)); // after: materialize up front byte[] bytes = socketStream.readAllBytes(); entity.setAttachment(lobHelper.createBlob(bytes));
Defensive patterns
Strategy: validation
Validate before calling
// ensure the stream is fully readable before handing it over
if (!stream.markSupported()) { /* wrap or materialize */ }
byte[] bytes = stream.readAllBytes(); // materialize once, up front
entity.setAttachment(lobHelper.createBlob(bytes)); Try / catch
try {
session.flush();
}
catch (HibernateException e) {
if (e.getCause() instanceof java.io.IOException io) {
// the backing stream failed: re-open source and rebind a materialized value
}
} Prevention
- Never read/close the InputStream you pass to createBlob
- Materialize byte[] when the source cannot stay open until commit
- Bind stream-backed LOBs late, close to flush time
When it happens
Trigger: A Blob/binary value created from an InputStream (e.g. Hibernate.getLobHelper().createBlob(stream, length)) whose underlying stream is already consumed, closed, or fails when Hibernate finally reads it at flush/bind time.
Common situations: Reading the provided InputStream yourself before handing it to Hibernate; streams over files/sockets/LOB locators that are closed between entity update and flush; deferred flushes after the stream source went away.
Related errors
- could not reset reader
- Underlying stream does not allow reset
- Unable to access blob stream
- IOException occurred reading a binary value
- IOException occurred reading text
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b5031598f3f23140.
Report an issue: GitHub.