hibernate/hibernate-orm · error · SQLException
Start position [<start>] cannot exceed overall CLOB length [
Error message
Start position [<start>] cannot exceed overall CLOB length [<length>]
What it means
In BlobProxy.getBinaryStream(long start, long length), start is checked against length() (the total blob size). A start greater than the total length means there is no byte at that position, so the proxy throws this SQLException. The message text says 'CLOB length' although this is a Blob proxy - a known copy/paste wart in the Hibernate source; the failing API is getBinaryStream(long, long) on a Blob.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/BlobProxy.java:202
}
@Override
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
- Bound the read: if (start <= blob.length()) ... before calling getBinaryStream(start, len)
- End chunked loops when the previous read returned fewer bytes than requested instead of pushing start past the end
- Special-case empty blobs (length() == 0): skip reading entirely
Example fix
// before
InputStream in = blob.getBinaryStream(start, chunk); // start may exceed length
// after
if (start <= blob.length()) {
InputStream in = blob.getBinaryStream(start, chunk);
} else {
return InputStream.nullInputStream();
} Defensive patterns
Strategy: validation
Validate before calling
static InputStream window(java.sql.Blob blob, long start, long length) throws SQLException {
long total = blob.length();
if (start < 1) throw new IllegalArgumentException("start must be >= 1");
if (start > total) return InputStream.nullInputStream(); // nothing at/after the end
return blob.getBinaryStream(start, length);
} Try / catch
try {
in = blob.getBinaryStream(start, length);
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("cannot exceed overall")) {
in = InputStream.nullInputStream(); // past the end: empty
} else {
throw e;
}
} Prevention
- Always compare start against blob.length() before positioned reads
- End chunking loops when a window returns short, not when an exception fires
- Remember the message says 'CLOB' even for Blobs - do not let that mislead diagnosis
When it happens
Trigger: Calling blob.getBinaryStream(start, len) with start > blob.length() (e.g. 100 on a 50-byte blob); a chunked-read loop whose start cursor runs one chunk past the end; using a stale cached length after the blob was replaced by a smaller one.
Common situations: Pagination/chunking over LOBs with a loop condition like while (true) { ... start += chunk; } without checking start <= length; empty blobs (length 0) where any start >= 1 exceeds the length; race between checking length() and the entity being reloaded.
Related errors
- Start position 1-based; must be 1 or more.
- Start position [${start}] cannot exceed overall CLOB length
- Length must be great-than-or-equal to zero.
- Can't deal with Blobs larger than 'Integer.MAX_VALUE'
- 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/ed9dbea1ddf01fb0.
Report an issue: GitHub.