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

BlobProxy.getBytes(long start, int length) rejects a negative length with this SQLException. The proxy honors the JDBC contract where a read of zero bytes is legal but a negative count is a caller bug, and it fails fast before touching the underlying stream.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/proxy/BlobProxy.java:151

	 *
	 * @return The BlobProxy instance to represent this data.
	 */
	public static Blob generateProxy(InputStream stream, long length) {
		return new BlobProxy( stream, length );
	}

	@Override
	public long length() throws SQLException {
		return binaryStream.getLength();
	}

	@Override
	public byte[] getBytes(final long start, final int length) throws SQLException {
		if ( start < 1 ) {
			throw new SQLException( "Start position 1-based; must be 1 or more." );
		}
		if ( length < 0 ) {
			throw new SQLException( "Length must be great-than-or-equal to zero." );
		}
		return DataHelper.extractBytes( getStream(), start-1, length );
	}

	@Override
	public InputStream getBinaryStream() throws SQLException {
		return getStream();
	}

	@Override
	public long position(byte[] pattern, long start) {
		throw notSupported();
	}

	@Override
	public long position(Blob pattern, long start) {
		throw notSupported();
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pass length >= 0; use 0 when you only want to validate start
  2. Clamp computed lengths: int len = Math.max(0, end - start)
  3. Never pipe indexOf/position() return values (-1 when not found) into getBytes without checking

Example fix

// before
int len = end - start; // may be negative
byte[] data = blob.getBytes(1, len);

// after
int len = Math.max(0, end - start);
byte[] data = blob.getBytes(1, len);
Defensive patterns

Strategy: validation

Validate before calling

static byte[] safeGetBytes(java.sql.Blob blob, long start, int length) throws SQLException {
    if (start < 1) throw new IllegalArgumentException("start must be 1-based (>= 1)");
    if (length < 0) length = 0;                     // negative read is a bug: read nothing
    return blob.getBytes(start, length);
}

Try / catch

try {
    data = blob.getBytes(start, length);
} catch (SQLException e) {
    if (e.getMessage() != null && e.getMessage().contains("Length must be")) {
        data = blob.getBytes(start, 0);             // degrade to empty read
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling blob.getBytes(1, -1) on a Hibernate-created Blob; computing length as end - start and passing it negative when end < start; a 'read remainder' helper defaulting length to -1 on error paths.

Common situations: Length arithmetic bugs such as length = endIndex - startIndex with reversed or clamped indices; sentinel values (-1) leaking from indexOf/position() results into getBytes; unit tests probing invalid input.

Related errors


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