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
- 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
- In tests, use a real database (Testcontainers) instead of mocked Connection/Statement, or make the mock return a row
- Disable or configure pool/agent statement interceptors that rewrite the settings queries
- 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
- Run pessimistic-lock integration tests against a real database (Testcontainers), never mocked Connections
- Keep pool init SQL and statement interceptors from rewriting SHOW / SELECT @@ settings queries
- Verify the settings query ('show lock_timeout', 'SELECT @@SESSION.innodb_lock_wait_timeout', 'select @@lock_timeout') returns one row on your pool
- Match JDBC driver versions to the actual server
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Unexpected PostgreSQL lock_timeout format: {}
- Exception pulsing TransactionCoordinator
- JDBC begin transaction failed:
- Unable to rollback against JDBC Connection
- JDBC driver does not support named parameters for setArray.
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7a4fa0a037dedcb4.
Report an issue: GitHub.