hibernate/hibernate-orm · error · HibernateException

Connection lock-timeout does not accept no-wait

Error message

Connection lock-timeout does not accept no-wait

What it means

Hibernate 7 applies pessimistic-lock timeouts on CockroachDB via the JDBC connection setting 'set lock_timeout = N' (CockroachLockingSupport.setLockTimeout -> Helper.setLockTimeout). The value strategy maps WAIT_FOREVER (-1 ms) to 0, so a timeout of 0 ms (Timeouts.NO_WAIT_MILLI, the JPA no-wait magic value) cannot be distinguished from wait-forever and is rejected with this HibernateException. The support level is SUPPORTED, not EXTENDED, so no-wait is never accepted on this path.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/CockroachLockingSupport.java:110

				connection,
				factory
		);
	}

	@Override
	public void setLockTimeout(
			Timeout timeout,
			Connection connection,
			SessionFactoryImplementor factory) {
		Helper.setLockTimeout(
				timeout,
				(t) -> {
					final int milliseconds = timeout.milliseconds();
					if ( milliseconds == SKIP_LOCKED_MILLI ) {
						throw new HibernateException( "Connection lock-timeout does not accept skip-locked" );
					}
					if ( milliseconds == NO_WAIT_MILLI ) {
						throw new HibernateException( "Connection lock-timeout does not accept no-wait" );
					}
					return milliseconds == WAIT_FOREVER_MILLI ? 0 : milliseconds;
				},
				"set lock_timeout = %s",
				connection,
				factory
		);
	}

}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use the smallest real timeout CockroachDB accepts (e.g. 1-50 ms) to approximate no-wait, or WAIT_FOREVER (-1) to wait indefinitely
  2. If you need true no-wait, use a locking clause variant supported by the database (native 'FOR UPDATE NOWAIT') instead of the connection-level timeout
  3. Check dialect.getLockingSupport().getConnectionLockTimeoutStrategy().getSupportedLevel(): only Level.EXTENDED (SQL Server/Sybase) accepts no-wait
  4. Remove global 'jakarta.persistence.lock.timeout' = 0 settings that apply to every pessimistic lock

Example fix

// before
Map<String, Object> hints = Map.of("jakarta.persistence.lock.timeout", 0); // NO_WAIT -> throws
em.find(Order.class, id, LockModeType.PESSIMISTIC_WRITE, hints);

// after: short real wait approximating no-wait on CockroachDB
Map<String, Object> hints = Map.of("jakarta.persistence.lock.timeout", 50);
em.find(Order.class, id, LockModeType.PESSIMISTIC_WRITE, hints);
Defensive patterns

Strategy: validation

Validate before calling

int millis = lockOptions.getTimeOut();
ConnectionLockTimeoutStrategy.Level level = sessionFactory.getJdbcServices().getDialect()
        .getLockingSupport().getConnectionLockTimeoutStrategy().getSupportedLevel();
if (millis == Timeouts.NO_WAIT_MILLI && level != ConnectionLockTimeoutStrategy.Level.EXTENDED) {
    lockOptions.setTimeOut(50); // 0 (no-wait) only works on EXTENDED dialects (SQL Server/Sybase)
}

Type guard

static boolean acceptsConnectionTimeout(ConnectionLockTimeoutStrategy s, int millis) {
    if (s.getSupportedLevel() == ConnectionLockTimeoutStrategy.Level.NONE) return false;
    if (millis == Timeouts.SKIP_LOCKED_MILLI) return false;
    return millis != Timeouts.NO_WAIT_MILLI
            || s.getSupportedLevel() == ConnectionLockTimeoutStrategy.Level.EXTENDED;
}

Try / catch

try {
    em.find(Order.class, id, LockModeType.PESSIMISTIC_WRITE, hints);
} catch (HibernateException e) {
    if (e.getMessage() != null && e.getMessage().contains("does not accept no-wait")) {
        hints = Map.of("jakarta.persistence.lock.timeout", 50); // retry with a real timeout
    } else { throw e; }
}

Prevention

When it happens

Trigger: session.buildLockRequest(LockOptions.UPGRADE_NOWAIT).lock(entity) or lockOptions.setTimeOut(0); em.find(id, PESSIMISTIC_WRITE, hints) with 'jakarta.persistence.lock.timeout'=0 (or legacy javax prefix); Timeouts.NO_WAIT reaching setLockTimeout when the dialect routes lock timeouts through the connection (LockTimeoutType.CONNECTION).

Common situations: Copy-pasted 'fail fast' locking code that uses the JPA hint value 0 for no-wait; a global lock.timeout=0 property in persistence.xml; switching an application from SQL Server (where no-wait works, Level.EXTENDED) to CockroachDB; Hibernate 6 to 7 migrations where lock timeout handling moved to ConnectionLockTimeoutStrategy.

Understand the failure class

Related errors


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