{"record":{"id":"7a4fa0a037dedcb4","repo":"hibernate/hibernate-orm","slug":"unable-to-query-jdbc-connection-for-current-lock-t","errorCode":null,"errorMessage":"Unable to query JDBC Connection for current lock-timeout setting (no result)","messagePattern":"Unable to query JDBC Connection for current lock-timeout setting \\(no result\\)","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/Helper.java","lineNumber":36,"sourceCode":" *\n * @author Steve Ebersole\n */\npublic class Helper {\n\t/**\n\t * Use the given {@code sql} statement to query the current lock-timeout for the\n\t * {@linkplain Connection} and use the {@code extractor} to process the value.\n\t */\n\tpublic static Timeout getLockTimeout(\n\t\t\tString sql,\n\t\t\tTimeoutExtractor extractor,\n\t\t\tConnection connection,\n\t\t\tSessionFactoryImplementor factory) {\n\t\ttry ( final var statement = connection.createStatement() ) {\n\t\t\tfactory.getJdbcServices().getSqlStatementLogger().logStatement( sql );\n\t\t\tfactory.getStatementObserver().performingSql( sql, -1 );\n\t\t\tfinal var results = statement.executeQuery( sql );\n\t\t\tif ( !results.next() ) {\n\t\t\t\tthrow new HibernateException( \"Unable to query JDBC Connection for current lock-timeout setting (no result)\" );\n\t\t\t}\n\t\t\treturn extractor.extractFrom( results );\n\t\t}\n\t\tcatch (SQLException sqle) {\n\t\t\tthrow factory.getJdbcServices().getJdbcEnvironment().getSqlExceptionHelper()\n\t\t\t\t\t.convert( sqle, \"Unable to query JDBC Connection for current lock-timeout setting\" );\n\t\t}\n\t}\n\n\t/**\n\t * Set the {@linkplain Connection}-level lock-timeout using the given {@code sql} command.\n\t */\n\tpublic static void setLockTimeout(\n\t\t\tString sql,\n\t\t\tConnection connection,\n\t\t\tSessionFactoryImplementor factory) {\n\t\ttry ( final var statement = connection.createStatement() ) {\n\t\t\tfactory.getJdbcServices().getSqlStatementLogger().logStatement( sql );","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/Helper.java#L18-L54","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before (mock returns no rows -> HibernateException at lock time)\nMockResultSet rs = new MockResultSet(); // empty\nwhen(statement.executeQuery(anyString())).thenReturn(rs);\n\n// after: settings query returns the single baseline row\nMockResultSet rs = new MockResultSet(new Object[][] { { \"30s\" } });\nwhen(statement.executeQuery(anyString())).thenReturn(rs);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_WRITE)).lock(entity);\n} catch (HibernateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"current lock-timeout setting (no result)\") ) {\n        // settings query returned no rows: verify connection health / interceptors\n        if (!connection.isValid(2)) throw new IllegalStateException(\"broken connection\", e);\n    }\n    throw e;\n}","preventionTips":["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"],"tags":["jdbc","lock-timeout","resultset","connection-pool","hibernate"],"backgroundTag":"lock-timeout-query-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}