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

ClobProxy.getSubString(long start, int length) checks start against length() + 1. JDBC allows start == length() + 1 (one past the last character, returning an empty string), but anything larger is invalid and throws this SQLException with the actual start and the overall CLOB length interpolated into the message.

Source

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

	}

	@Override
	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 ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Guard the call: if (start <= clob.length() + 1) before reading
  2. Terminate windowing loops when the previous read returns fewer characters than requested
  3. For empty Clobs skip reading altogether

Example fix

// before
String part = clob.getSubString(start, 100); // start may be past the end

// after
long maxStart = clob.length() + 1;
String part = start <= maxStart ? clob.getSubString(start, 100) : "";
Defensive patterns

Strategy: validation

Validate before calling

static String window(java.sql.Clob clob, long start, int length) throws SQLException {
    long maxStart = clob.length() + 1;              // start == maxStart yields ""
    if (start < 1) throw new IllegalArgumentException("start must be >= 1");
    if (start > maxStart) return "";                // fully past the end: empty
    return clob.getSubString(start, length);
}

Try / catch

try {
    s = clob.getSubString(start, length);
} catch (SQLException e) {
    if (e.getMessage() != null && e.getMessage().contains("cannot exceed overall")) {
        s = "";                                     // past the end: empty result
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling getSubString(start, n) with start > clob.length() + 1 (e.g. 60 on a 50-char Clob); a windowing loop whose cursor advances past the end; using a stale length after the Clob content shrank.

Common situations: Text pagination loops without an end bound; empty Clobs (length 0) where any start > 1 fails; off-by-one ports of String.substring where end index is fed as start.

Related errors


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