hibernate/hibernate-orm · error · HibernateException

Connection lock-timeout does not accept skip-locked

Error message

Connection lock-timeout does not accept skip-locked

What it means

Informix manages lock waits through the connection-level 'SET LOCK MODE' statement. Hibernate's InformixLockingSupport.setLockTimeout() maps the requested Timeout to that statement, but SKIP_LOCKED is a select-style hint with no 'SET LOCK MODE' equivalent, so requesting a skip-locked lock timeout raises HibernateException with this message.

Source

Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixLockingSupport.java:85

				"select scs_lockmode from sysmaster:syssqlcurses where scs_sessionid = dbinfo('sessionid')",
				(resultSet) -> {
					final int seconds = resultSet.getInt( 1 );
					return switch ( seconds ) {
						case -1 -> Timeouts.WAIT_FOREVER;
						case 0 -> Timeouts.NO_WAIT;
						default -> Timeout.seconds( seconds );
					};
				},
				connection,
				factory
		);
	}

	@Override
	public void setLockTimeout(Timeout timeout, Connection connection, SessionFactoryImplementor factory) {
		final int milliseconds = timeout.milliseconds();
		if ( milliseconds == SKIP_LOCKED_MILLI ) {
			throw new HibernateException( "Connection lock-timeout does not accept skip-locked" );
		}
		if ( milliseconds == WAIT_FOREVER_MILLI ) {
			Helper.setLockTimeout(
					"set lock mode to wait",
					connection,
					factory
			);
		}
		else if ( milliseconds == NO_WAIT_MILLI ) {
			Helper.setLockTimeout(
					"set lock mode to not wait",
					connection,
					factory
			);
		}
		else {
			Helper.setLockTimeout(
					(int) Math.ceil( (double) milliseconds / 1000),

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove the skip-locked option on Informix: use LockOptions.NO_WAIT or a short wait timeout for polling loops
  2. Implement the queue pattern without pessimistic skip-locked: optimistic @Version-based claiming (UPDATE ... WHERE status=...) or a database-native mechanism
  3. Gate locking strategy per database: check the dialect before applying skip-locked options

Example fix

// before
LockOptions opts = new LockOptions(LockMode.PESSIMISTIC_WRITE).setSkipLocked(true);
session.find(Item.class, id, opts); // -> HibernateException on Informix

// after - poll with no-wait and retry on cannot-acquire
LockOptions opts = new LockOptions(LockMode.PESSIMISTIC_WRITE)
        .setTimeOut(LockOptions.NO_WAIT);
try { session.find(Item.class, id, opts); }
catch (PessimisticLockException e) { /* another worker holds it */ }
Defensive patterns

Strategy: validation

Validate before calling

boolean wantSkipLocked = /* requested by caller */;
if ( session.getJdbcServices().getDialect() instanceof InformixDialect && wantSkipLocked ) {
    // Informix: no connection-level skip-locked; degrade to NO_WAIT polling
    lockOptions.setTimeOut(LockOptions.NO_WAIT);
    lockOptions.setSkipLocked(false);
}

Type guard

static boolean isInformix(Dialect d) { return d instanceof InformixDialect; }

Try / catch

try {
    session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_WRITE).setSkipLocked(true))
           .lock(item);
} catch (HibernateException e) {
    if ( String.valueOf(e.getMessage()).contains("skip-locked") ) {
        // fall back to optimistic claiming: UPDATE ... WHERE status = 'NEW'
    }
    throw e;
}

Prevention

When it happens

Trigger: Requesting pessimistic locking with skip-locked on Informix, e.g. LockOptions with setSkipLocked(true) (or a lock timeout of Timeout.SKIP_LOCKED / jakarta.persistence.lock.timeout=-2) together with a connection-level lock timeout, so setLockTimeout() receives SKIP_LOCKED_MILLI and throws.

Common situations: Porting a job-queue pattern ('select next item for update skip locked') from PostgreSQL/Oracle to Informix; setting jakarta.persistence.lock.timeout=-2 globally in persistence.xml and then running on Informix; generic locking helper code applied uniformly across databases.

Understand the failure class

Related errors


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