hibernate/hibernate-orm · error · HibernateException

Unable to access lob stream

Error message

Unable to access lob stream

What it means

DataHelper.extractString(Clob) opens value.getCharacterStream() and asks the Clob for its length (determineLengthForBufferSizing, backed by Clob.length()); any SQLException from those calls is wrapped as HibernateException('Unable to access lob stream'). This fails before a single character is read — the driver refused to hand out or measure the LOB.

Source

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

	}

	/**
	 * Extract the contents of the given Clob as a string.
	 *
	 * @param value The clob to to be extracted from
	 *
	 * @return The content as string
	 */
	public static String extractString(final Clob value) {
		try {
			final var characterStream = value.getCharacterStream();
			final long length = determineLengthForBufferSizing( value );
			return length > Integer.MAX_VALUE
					? extractString( characterStream, Integer.MAX_VALUE )
					: extractString( characterStream, (int) length );
		}
		catch ( SQLException e ) {
			throw new HibernateException( "Unable to access lob stream", e );
		}
	}

	/**
	 * Determine a buffer size for reading the underlying character stream.
	 *
	 * @param value The Clob value
	 *
	 * @return The appropriate buffer size ({@link Clob#length()} by default.
	 *
	 */
	private static long determineLengthForBufferSizing(Clob value) throws SQLException {
		try {
			return value.length();
		}
		catch ( SQLFeatureNotSupportedException e ) {
			return BUFFER_SIZE;
		}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Convert the Clob to String while the connection and transaction are alive — materialize before detaching
  2. Never hold Clob objects in long-lived state; store the extracted String instead
  3. Check that nothing (code, pool wrapper, driver) called Clob.free() before the read
  4. Upgrade the JDBC driver if its Clob implementation lacks stream support

Example fix

// before
Clob c = rs.getClob(1);
// ... later, after tx commit
String s = extractText(c); // SQLException -> Unable to access lob stream

// after
Clob c = rs.getClob(1);
String s = c.getSubString(1, (int) c.length()); // materialize immediately, detach the String
Defensive patterns

Strategy: try-catch

Try / catch

try {
    String s = DataHelper.extractString(clob);
} catch (HibernateException e) {
    if (e.getCause() instanceof SQLException se) {
        // lob freed/closed or connection gone: re-fetch the row in a fresh tx
    }
}

Prevention

When it happens

Trigger: Clob.getCharacterStream() or Clob.length() throwing: the LOB was already freed or closed (Oracle frees temporary LOBs at transaction end), the connection is closed, something called Clob.free() prematurely, or the driver's Clob implementation does not support the call.

Common situations: Detached entities or web requests carrying Clob objects across transaction boundaries; proxying or wrapping JDBC objects; keeping Clob references in caches or HTTP sessions.

Related errors


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