hibernate/hibernate-orm · error · SQLException

Length must be great-than-or-equal to zero.

Error message

Length must be great-than-or-equal to zero.

What it means

ClobProxy.getSubString(long start, int length) rejects a negative length with this SQLException (note the typo 'great-than-or-equal' in the Hibernate message). Zero is a legal length, but a negative count is a caller bug and fails fast before the substring is computed.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/ClobProxy.java:132

	public Writer setCharacterStream(long pos) {
		throw notSupported();
	}

	@Override
	public void truncate(long len) throws SQLException {
		throw notSupported();
	}

	@Override
	public String getSubString(long start, int 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 < 0 ) {
			throw new SQLException( "Length must be great-than-or-equal to zero." );
		}
		final String string = characterStream.asString();
		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 ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pass length >= 0; use 0 to validate start without reading
  2. Clamp computed lengths: int len = Math.max(0, end - start)
  3. Check indexOf results for -1 before deriving lengths from them

Example fix

// before
int idx = content.indexOf(marker);
String s = clob.getSubString(1, idx); // idx == -1 throws

// after
int idx = content.indexOf(marker);
String s = clob.getSubString(1, Math.max(0, idx));
Defensive patterns

Strategy: validation

Validate before calling

static String safeSubString(java.sql.Clob clob, long start, int length) throws SQLException {
    if (start < 1) throw new IllegalArgumentException("start must be >= 1");
    if (length < 0) length = 0;                     // negative means 'read nothing'
    return clob.getSubString(start, length);
}

Try / catch

try {
    s = clob.getSubString(start, length);
} catch (SQLException e) {
    if (e.getMessage() != null && e.getMessage().contains("Length must be")) {
        s = "";                                     // degrade to empty string
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling clob.getSubString(1, -1); computing length = end - start and passing it negative when end < start; forwarding a -1 from String.indexOf (not found) into getSubString.

Common situations: Sentinel -1 values from indexOf/lastIndexOf leaking into substring extraction; reversed or clamped index arithmetic; 'read rest' helpers with an uninitialized size.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/612f20b052e338f0. Report an issue: GitHub.