hibernate/hibernate-orm · error · HibernateException

Unable to skip needed bytes

Error message

Unable to skip needed bytes

What it means

In the substring variant extractString(Reader characterStream, long start, int length), Hibernate first positions the stream with characterStream.skip(start); if the reader reports skipping fewer characters than requested, it throws HibernateException('Unable to skip needed bytes') before reading anything. It fires when the LOB reader cannot seek — usually because the stream is shorter than start or the driver's skip() is not fully conformant.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DataHelper.java:103

	/**
	 * Extracts a portion of the contents of the given reader/stream as a string.
	 *
	 * @param characterStream The reader for the content
	 * @param start The start position/offset (0-based, per general stream/reader contracts).
	 * @param length The amount to extract
	 *
	 * @return The content as string
	 */
	private static String extractString(Reader characterStream, long start, int length) {
		if ( length == 0 ) {
			return "";
		}
		final var stringBuilder = new StringBuilder( length );
		try {
			final long skipped = characterStream.skip( start );
			if ( skipped != start ) {
				throw new HibernateException( "Unable to skip needed bytes" );
			}
			final int bufferSize = getSuggestedBufferSize( length );
			final char[] buffer = new char[bufferSize];
			int charsRead = 0;
			while ( true ) {
				final int amountRead = characterStream.read( buffer, 0, bufferSize );
				if ( amountRead == -1 ) {
					break;
				}
				stringBuilder.append( buffer, 0, amountRead );
				if ( amountRead < bufferSize ) {
					// we have read up to the end of stream
					break;
				}
				charsRead += amountRead;
				if ( charsRead >= length ) {
					break;
				}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Validate offsets against Clob.length() before extraction and clamp start to the actual length
  2. Upgrade the JDBC driver — skip() conformance bugs are a known driver issue
  3. Avoid partial reads: read the whole CLOB and substring in Java via Clob.getSubString
  4. Re-read the row in a fresh transaction if the LOB can change concurrently

Example fix

// before
Reader r = clob.getCharacterStream();
String part = extractBySkip(r, 500, 100); // may fail: skipped != 500

// after
String all = clob.getSubString(1, (int) clob.length());
String part = all.substring(500, Math.min(600, all.length()));
Defensive patterns

Strategy: validation

Validate before calling

long len = clob.length();
if (start < 0 || start >= len) {
    throw new IllegalArgumentException("start " + start + " outside LOB length " + len);
}

Prevention

When it happens

Trigger: Partial CLOB extraction (the start/length paths) where the character stream ends before start; a driver Reader whose skip() legitimately returns less than n; start offsets computed from stale length metadata.

Common situations: Concurrent truncation of the row's LOB between length computation and read; locator-based LOBs on drivers with weak skip support; offsets derived from a previous read of the row.

Related errors


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