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
- Use a small real timeout (e.g. 10-100 ms) and treat PessimisticLockException as 'busy'
- 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
- Verify Level via getSupportedLevel(): only EXTENDED (SQL Server/Sybase) accepts no-wait through the connection
- 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
- Remember PG lock_timeout=0 disables the timeout: Hibernate rightly refuses no-wait there
- Use very small positive timeouts plus PessimisticLockException handling for fail-fast
- Use FOR UPDATE NOWAIT (native or clause-level) for genuine no-wait
- Keep per-database lock timeout profiles instead of one global hint
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Connection lock-timeout does not accept no-wait
- Connection lock-timeout does not accept no-wait
- Connection lock-timeout does not accept skip-locked
- Connection lock-timeout does not accept skip-locked
- Connection lock-timeout does not accept skip-locked
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/623527146d2a082f.
Report an issue: GitHub.