hibernate/hibernate-orm · error · HibernateException

Sybase does not accept skip-locked for lock-timeout

Error message

Sybase does not accept skip-locked for lock-timeout

What it means

TransactSQLLockingSupport.SybaseImpl applies lock timeouts on Sybase with 'set lock wait N', where N is whole seconds (range 0-21474483647 per Sybase's 'lock wait period'). SKIP_LOCKED (-2 ms) has no representation in that command - skip-locked is a row-locking clause concept - so SybaseImpl throws this HibernateException. Note WAIT_FOREVER is handled by issuing a bare 'set lock wait' (reset to server default) and no-wait (0) is accepted since the level is EXTENDED.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/TransactSQLLockingSupport.java:193

		}

		@Override
		public void setLockTimeout(Timeout timeout, Connection connection, SessionFactoryImplementor factory) {
			// see https://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc31654.1600/doc/html/san1360629104549.html
			// SAP Adaptive Server Enterprise 16.0
			// > System Administration Guide 16.0: Volume 1
			//   > Setting Configuration Parameters
			//     > Configuration Parameters
			//       > Alphabetical Listing of Configuration Parameters
			//         > lock wait period
			//
			// range:   0 – 2147483647
			// default: 2147483647
			// unit:    seconds
			final int milliseconds = timeout.milliseconds();

			if ( milliseconds == Timeouts.SKIP_LOCKED_MILLI ) {
				throw new HibernateException( "Sybase does not accept skip-locked for lock-timeout" );
			}

			if ( milliseconds == Timeouts.WAIT_FOREVER_MILLI ) {
				// Even though Sybase's wait-forever (and default) value is -1, it won't accept
				// -1 as a value because, well, of course it won't.  Need to omit the argument to reset it
				Helper.setLockTimeout( "set lock wait", connection, factory );
			}
			else {
				Helper.setLockTimeout( (int) Math.ceil( (double) milliseconds / 1000), "set lock wait %s", connection, factory );
			}
		}
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a real positive timeout in ms (SybaseImpl rounds up to seconds) or WAIT_FOREVER (-1); use 0 for no-wait (supported here)
  2. Implement skip-locked semantics with native SQL appropriate to Sybase (e.g. READPAST-style behavior) instead of the timeout value
  3. Check getSupportedLevel() (EXTENDED on Sybase) and never feed SKIP_LOCKED to connection-level timeouts
  4. Remove -2 lock timeout hints from configuration shared across databases

Example fix

// before
LockOptions options = new LockOptions(LockMode.PESSIMISTIC_WRITE).setTimeout(LockOptions.SKIP_LOCKED); // -2 -> throws
session.buildLockRequest(options).lock(entity);

// after
LockOptions options = new LockOptions(LockMode.PESSIMISTIC_WRITE).setTimeout(5000); // 5s wait
session.buildLockRequest(options).lock(entity);
Defensive patterns

Strategy: validation

Validate before calling

int millis = lockOptions.getTimeOut();
if (millis == Timeouts.SKIP_LOCKED_MILLI) {
    lockOptions.setTimeOut(5000); // 'set lock wait' (seconds) cannot express skip-locked
}

Type guard

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

Try / catch

try {
    session.buildLockRequest(lockOptions).lock(entity);
} catch (HibernateException e) {
    if (e.getMessage() != null && e.getMessage().contains("skip-locked")) {
        lockOptions.setTimeout(5000);
        session.buildLockRequest(lockOptions).lock(entity);
    } else { throw e; }
}

Prevention

When it happens

Trigger: session.buildLockRequest(LockOptions.UPGRADE_SKIPLOCKED).lock(entity) / lockOptions.setTimeOut(-2); em.find(id, PESSIMISTIC_WRITE, hints) or locking queries with 'jakarta.persistence.lock.timeout' = -2 on Sybase ASE via the connection-timeout path (LockTimeoutType.CONNECTION).

Common situations: Porting skip-locked job-queue patterns to Sybase; global lock.timeout hints set to -2 in shared persistence.xml; reusable locking utility code assumed database-agnostic; Hibernate 7 migration introducing the ConnectionLockTimeoutStrategy plumbing.

Understand the failure class

Related errors


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