hibernate/hibernate-orm · error · SQLException
Can't deal with Blobs larger than 'Integer.MAX_VALUE'
Error message
Can't deal with Blobs larger than 'Integer.MAX_VALUE'
What it means
BlobProxy.getBinaryStream(long start, long length) can only produce a sub-stream whose length fits an int, because it ultimately casts length to int for DataHelper.subStream. A length argument above Integer.MAX_VALUE is rejected with this SQLException rather than being silently truncated.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/BlobProxy.java:205
public void truncate(long len) {
throw notSupported();
}
@Override
public void free() {
binaryStream.release();
}
@Override
public InputStream getBinaryStream(final long start, final long length) throws SQLException {
if ( start < 1 ) {
throw new SQLException( "Start position 1-based; must be 1 or more." );
}
if ( start > length() ) {
throw new SQLException( "Start position [" + start + "] cannot exceed overall CLOB length [" + length() + "]" );
}
if ( length > Integer.MAX_VALUE ) {
throw new SQLException( "Can't deal with Blobs larger than 'Integer.MAX_VALUE'" );
}
if ( length < 0 ) {
// javadoc for getBinaryStream(long,int) specifies that the start+length must not exceed the
// total length (this is at odds with the behavior of getBytes(long,int))
throw new SQLException( "Length must be great-than-or-equal to zero." );
}
return DataHelper.subStream( getStream(), start-1, (int)length );
}
private static UnsupportedOperationException notSupported() {
return new UnsupportedOperationException( "Blob may not be manipulated from creating session" );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Read in chunks: loop with length capped at e.g. 8 MB per call
- For whole-stream access use getBinaryStream() (no args) and stream-copy instead of fixed windows
- Replace 'read all' sentinels like Long.MAX_VALUE with the real remaining length
Example fix
// before InputStream all = blob.getBinaryStream(1, Long.MAX_VALUE); // throws // after InputStream all = blob.getBinaryStream(); // full stream, copy incrementally
Defensive patterns
Strategy: validation
Validate before calling
static final long MAX_WINDOW = 8L * 1024 * 1024; // 8 MiB per call
static long cappedWindow(long requested, long remaining) {
if (requested < 0) throw new IllegalArgumentException("length must be >= 0");
return Math.min(Math.min(requested, remaining), MAX_WINDOW);
}
// usage: blob.getBinaryStream(start, cappedWindow(len, blob.length() - start + 1)) Try / catch
try {
in = blob.getBinaryStream(start, length);
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("Integer.MAX_VALUE")) {
in = blob.getBinaryStream(); // fall back to the full stream
} else {
throw e;
}
} Prevention
- Never pass Long.MAX_VALUE or blob.length() of a multi-GB LOB as the window size
- Cap every positioned read at a few MiB and loop
- Use the no-arg getBinaryStream() plus incremental copy for whole-content access
When it happens
Trigger: Calling blob.getBinaryStream(1, blob.length()) when the blob exceeds Integer.MAX_VALUE bytes; passing Long.MAX_VALUE as an 'until the end' marker; generic copy utilities that forward a user-supplied long maxSize.
Common situations: Multi-GB LOBs (video, genomics, backups) stored in databases with huge-lob support; helper APIs that accept long sizes from HTTP Range headers; migrating from drivers that clamp silently to Hibernate's proxy which fails fast.
Related errors
- Can't deal with Clobs larger than 'Integer.MAX_VALUE'
- Could not create JDBC Blob
- Start position 1-based; must be 1 or more.
- Length must be great-than-or-equal to zero.
- Start position [<start>] cannot exceed overall CLOB length [
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/736bc3649cdd6baa.
Report an issue: GitHub.