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

On PostgreSQL, Hibernate applies pessimistic-lock timeouts with 'set local lock_timeout = N' (N in milliseconds). Because lock_timeout=0 in PostgreSQL disables the timeout (wait forever), the JPA no-wait magic value 0 ms cannot be mapped without inverting its meaning, so PostgreSQLLockingSupport throws this HibernateException. Level is SUPPORTED, not EXTENDED - no-wait is not accepted through the connection on PostgreSQL (use 'FOR UPDATE NOWAIT' at clause level instead).

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/PostgreSQLLockingSupport.java:124

					};
				},
				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 local lock_timeout = %s",
				connection,
				factory
		);
	}

	private static int findUnitStartIndex(String value) {
		for ( int i = value.length() - 1; i >= 0; i-- ) {
			if ( Character.isDigit( value.charAt( i ) ) ) {
				return i + 1;
			}
		}
		return -1;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a small real timeout (e.g. 10-100 ms) and treat PessimisticLockException as 'busy'
  2. For genuine no-wait, use 'FOR UPDATE NOWAIT' semantics: the locking clause (LockMode.UPGRADE_NOWAIT via clause strategy) or a native query, not the connection timeout
  3. Verify Level via getSupportedLevel(): only EXTENDED (SQL Server/Sybase) accepts no-wait through the connection
  4. Audit configuration for lock.timeout hints equal to 0

Example fix

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

// after
Map<String, Object> hints = Map.of("jakarta.persistence.lock.timeout", 50);
try {
    Order o = em.find(Order.class, id, LockModeType.PESSIMISTIC_WRITE, hints);
} catch (PessimisticLockException e) { /* busy -> fail fast */ }
Defensive patterns

Strategy: validation

Validate before calling

int millis = lockOptions.getTimeOut();
if (millis == Timeouts.NO_WAIT_MILLI) {
    // PG lock_timeout=0 means wait forever, so no-wait must come from NOWAIT clause
    lockOptions.setTimeOut(50);
}

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);
        try { return em.find(Order.class, id, LockModeType.PESSIMISTIC_WRITE, hints); }
        catch (PessimisticLockException busy) { return null; }
    }
    throw e;
}

Prevention

When it happens

Trigger: session.buildLockRequest(LockOptions.UPGRADE_NOWAIT).lock(entity) / lockOptions.setTimeOut(0); em.find(id, PESSIMISTIC_WRITE, hints) or locking queries with 'jakarta.persistence.lock.timeout' = 0; Timeouts.NO_WAIT reaching setLockTimeout when LockTimeoutType.CONNECTION applies.

Common situations: Standard JPA 'no-wait' recipes (lock.timeout=0) that predate Hibernate 7's connection-timeout handling; shared entity/repo code run against both PostgreSQL and SQL Server; global persistence.xml lock timeout property set to 0; documentation-copied hints applied to every pessimistic operation.

Understand the failure class

Related errors


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