hibernate/hibernate-orm · error · HibernateException

Unable to query JDBC Connection for current lock-timeout set

Error message

Unable to query JDBC Connection for current lock-timeout setting (no result)

What it means

Before applying a connection-level lock timeout, Hibernate reads the current baseline by executing a settings query (e.g. 'show lock_timeout' on PostgreSQL, 'SELECT @@SESSION.innodb_lock_wait_timeout' on MySQL, 'select @@lock_timeout' on SQL Server/Sybase) in Helper.getLockTimeout. This HibernateException means the statement executed without a SQLException but the ResultSet contained no rows, so Hibernate has no baseline value to restore afterwards (LockTimeoutHandler.performPostAction). On a healthy database these queries always return exactly one row, so an empty result almost always indicates an interception layer or a stubbed Connection.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/Helper.java:36

 *
 * @author Steve Ebersole
 */
public class Helper {
	/**
	 * Use the given {@code sql} statement to query the current lock-timeout for the
	 * {@linkplain Connection} and use the {@code extractor} to process the value.
	 */
	public static Timeout getLockTimeout(
			String sql,
			TimeoutExtractor extractor,
			Connection connection,
			SessionFactoryImplementor factory) {
		try ( final var statement = connection.createStatement() ) {
			factory.getJdbcServices().getSqlStatementLogger().logStatement( sql );
			factory.getStatementObserver().performingSql( sql, -1 );
			final var results = statement.executeQuery( sql );
			if ( !results.next() ) {
				throw new HibernateException( "Unable to query JDBC Connection for current lock-timeout setting (no result)" );
			}
			return extractor.extractFrom( results );
		}
		catch (SQLException sqle) {
			throw factory.getJdbcServices().getJdbcEnvironment().getSqlExceptionHelper()
					.convert( sqle, "Unable to query JDBC Connection for current lock-timeout setting" );
		}
	}

	/**
	 * Set the {@linkplain Connection}-level lock-timeout using the given {@code sql} command.
	 */
	public static void setLockTimeout(
			String sql,
			Connection connection,
			SessionFactoryImplementor factory) {
		try ( final var statement = connection.createStatement() ) {
			factory.getJdbcServices().getSqlStatementLogger().logStatement( sql );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Reproduce manually: run the dialect's settings query (e.g. 'show lock_timeout' or 'SELECT @@SESSION.innodb_lock_wait_timeout') over the exact same pooled connection - it must return one row
  2. In tests, use a real database (Testcontainers) instead of mocked Connection/Statement, or make the mock return a row
  3. Disable or configure pool/agent statement interceptors that rewrite the settings queries
  4. Verify the JDBC driver actually matches the target database and version (no protocol emulation)

Example fix

// before (mock returns no rows -> HibernateException at lock time)
MockResultSet rs = new MockResultSet(); // empty
when(statement.executeQuery(anyString())).thenReturn(rs);

// after: settings query returns the single baseline row
MockResultSet rs = new MockResultSet(new Object[][] { { "30s" } });
when(statement.executeQuery(anyString())).thenReturn(rs);
Defensive patterns

Strategy: try-catch

Try / catch

try {
    session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_WRITE)).lock(entity);
} catch (HibernateException e) {
    if (e.getMessage() != null && e.getMessage().contains("current lock-timeout setting (no result)") ) {
        // settings query returned no rows: verify connection health / interceptors
        if (!connection.isValid(2)) throw new IllegalStateException("broken connection", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Any pessimistic lock on a dialect whose LockTimeoutType is CONNECTION (PostgreSQL, MySQL/MariaDB, SQL Server, Sybase families): LockTimeoutHandler.performPreAction calls getLockTimeout first and the settings query returns zero rows. Typical culprits: unit tests with Mockito-mocked Connection/Statement returning an empty ResultSet; JDBC wrappers/observability agents or connection pools that rewrite or swallow the settings statement; proxies emulating the protocol imperfectly.

Common situations: Running the full SessionFactory pipeline against mocked JDBC objects in tests; database proxies or shims (protocol-emulating sidecars, serverless drivers) that mishandle SHOW/SELECT @@ statements; driver versions that emulate another database's protocol; custom statement interceptors in the connection pool.

Understand the failure class

Related errors


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