hibernate/hibernate-orm · error · SQLException
Length must be greater than or equal to zero
Error message
Length must be greater than or equal to zero
What it means
In ClobProxy.getCharacterStream(long start, long length) a negative length is rejected with this SQLException (message variant without the period, distinct from the getSubString message). The source comment notes the JDBC javadoc requires start+length to stay within the Clob, so a negative length is a caller bug caught before the sub-stream is created. The check is unreachable for values above Integer.MAX_VALUE, which the preceding check already rejected.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/ClobProxy.java:153
final long endIndex = Math.min( start + length - 1, string.length() );
return string.substring( (int) start - 1, (int) endIndex );
}
@Override
public Reader getCharacterStream(long start, long length) throws SQLException {
if ( start < 1 ) {
throw new SQLException( "Start position 1-based; must be 1 or more." );
}
if ( start > length() + 1 ) {
throw new SQLException( "Start position [" + start + "] cannot exceed overall CLOB length [" + length() + "]" );
}
if ( length > Integer.MAX_VALUE ) {
throw new SQLException( "Can't deal with Clobs larger than 'Integer.MAX_VALUE'" );
}
if ( length < 0 ) {
// javadoc for getCharacterStream(long,int) specifies that the start+length must not exceed the
// total length (this is at odds with the behavior of getSubString(long,int))
throw new SQLException( "Length must be greater than or equal to zero" );
}
return DataHelper.subStream( getCharacterStream(), start-1, (int) length );
}
@Override
public void free() throws SQLException {
characterStream.release();
}
protected void resetIfNeeded() {
try {
if ( needsReset ) {
characterStream.asReader().reset();
}
}
catch ( IOException ioe ) {
throw new HibernateException( "could not reset reader", ioe );
}View on GitHub (pinned to fad1729dce)
Solutions
- Pass length >= 0 (0 is legal, yielding an empty reader)
- Clamp remaining counts: long len = Math.max(0L, remaining)
- Translate 'unlimited' sentinels to the true remaining length before the call
Example fix
// before
Reader r = clob.getCharacterStream(1, remaining); // remaining < 0
// after
long len = Math.max(0L, remaining);
if (len > 0) { Reader r = clob.getCharacterStream(1, len); } Defensive patterns
Strategy: validation
Validate before calling
static Reader safeReader(java.sql.Clob clob, long start, long length) throws SQLException {
if (start < 1) throw new IllegalArgumentException("start must be >= 1");
long len = Math.max(0L, length); // negative length means 'nothing'
return clob.getCharacterStream(start, len);
} Try / catch
try {
r = clob.getCharacterStream(start, length);
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().contains("greater than or equal to zero")) {
r = clob.getCharacterStream(start, 0); // degrade to empty reader
} else {
throw e;
}
} Prevention
- Floor all remaining-character computations at zero
- Resolve 'unlimited' configuration sentinels to the true remaining count before the call
- Note this message has no trailing period - match text carefully when catching
When it happens
Trigger: Calling clob.getCharacterStream(1, -1); a remaining-chars computation (total - consumed) going negative after the content is exhausted; forwarding a -1 'unlimited' sentinel from configuration.
Common situations: Windowed streaming loops that underflow at the end of the content; optional size parameters defaulting to -1; tests probing invalid arguments.
Related errors
- Length must be great-than-or-equal to zero.
- Length must be great-than-or-equal to zero.
- Start position 1-based; must be 1 or more.
- Start position [${start}] cannot exceed overall CLOB length
- Can't deal with Clobs larger than 'Integer.MAX_VALUE'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7c2a7303f78368a0.
Report an issue: GitHub.