hibernate/hibernate-orm · error · HibernateException
IOException occurred reading a binary value
Error message
IOException occurred reading a binary value
What it means
Same read loop as the whole-stream variant, but inside extractString(Reader, long start, int length): any IOException raised while reading characters after a successful skip is wrapped as HibernateException. The message says 'binary value' although this path reads characters — a copy-paste artifact in DataHelper; treat it as a text-stream failure.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DataHelper.java:125
int charsRead = 0;
while ( true ) {
final int amountRead = characterStream.read( buffer, 0, bufferSize );
if ( amountRead == -1 ) {
break;
}
stringBuilder.append( buffer, 0, amountRead );
if ( amountRead < bufferSize ) {
// we have read up to the end of stream
break;
}
charsRead += amountRead;
if ( charsRead >= length ) {
break;
}
}
}
catch ( IOException ioe ) {
throw new HibernateException( "IOException occurred reading a binary value", ioe );
}
return stringBuilder.toString();
}
/**
* Extract a portion of a reader, wrapping the portion in a new reader.
*
* @param characterStream The reader for the content
* @param start The start position/offset (0-based, per general stream/reader contracts).
* @param length The amount to extract
*
* @return The content portion as a reader
*/
public static Reader subStream(Reader characterStream, long start, int length) {
return new StringReader( extractString( characterStream, start, length ) );
}
/**View on GitHub (pinned to fad1729dce)
Solutions
- Extract LOB portions immediately on the live ResultSet, inside the open transaction
- Retry the read once in a fresh transaction — transient IO failures are common here
- Classify via getCause() (timeout vs closed vs reset) and tune socket/statement timeouts or driver settings accordingly
- Prefer full reads plus in-memory substring over stream skipping
Example fix
// before: reader obtained from an earlier ResultSet, session since closed String part = extractString(reader, start, len); // IOException mid-read // after: perform the extraction on the live ResultSet/session scope String all = clob.getSubString(1, (int) clob.length());
Defensive patterns
Strategy: try-catch
Try / catch
try {
return extractPortion(clob, start, length);
} catch (HibernateException e) {
if (e.getCause() instanceof IOException) {
// re-open in a fresh transaction and retry once, then surface
}
} Prevention
- Extract LOB portions immediately on the live ResultSet
- Do not cache Readers across requests or transactions
- Close sessions only after LOB materialization completes
When it happens
Trigger: Partial CLOB reads (start/length) where the stream breaks mid-read: connection reset, the LOB was invalidated by an intervening commit, or the driver tied the stream's lifetime to a ResultSet that was already closed.
Common situations: Reading substring-shaped LOB data on Oracle/PostgreSQL; racing session close or commit against the read; network drops during extraction.
Related errors
- could not reset reader
- IOException occurred reading text
- Unable to set CLOB string after creation
- Could not create JDBC Clob
- Start position 1-based; must be 1 or more.
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/d48a99ca96e5ca4f.
Report an issue: GitHub.