{"record":{"id":"cfc8157e0aff3eda","repo":"hibernate/hibernate-orm","slug":"sybase-does-not-accept-skip-locked-for-lock-timeou","errorCode":null,"errorMessage":"Sybase does not accept skip-locked for lock-timeout","messagePattern":"Sybase does not accept skip-locked for lock-timeout","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/TransactSQLLockingSupport.java","lineNumber":193,"sourceCode":"\t\t}\n\n\t\t@Override\n\t\tpublic void setLockTimeout(Timeout timeout, Connection connection, SessionFactoryImplementor factory) {\n\t\t\t// see https://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc31654.1600/doc/html/san1360629104549.html\n\t\t\t// SAP Adaptive Server Enterprise 16.0\n\t\t\t// > System Administration Guide 16.0: Volume 1\n\t\t\t//   > Setting Configuration Parameters\n\t\t\t//     > Configuration Parameters\n\t\t\t//       > Alphabetical Listing of Configuration Parameters\n\t\t\t//         > lock wait period\n\t\t\t//\n\t\t\t// range:   0 – 2147483647\n\t\t\t// default: 2147483647\n\t\t\t// unit:    seconds\n\t\t\tfinal int milliseconds = timeout.milliseconds();\n\n\t\t\tif ( milliseconds == Timeouts.SKIP_LOCKED_MILLI ) {\n\t\t\t\tthrow new HibernateException( \"Sybase does not accept skip-locked for lock-timeout\" );\n\t\t\t}\n\n\t\t\tif ( milliseconds == Timeouts.WAIT_FOREVER_MILLI ) {\n\t\t\t\t// Even though Sybase's wait-forever (and default) value is -1, it won't accept\n\t\t\t\t// -1 as a value because, well, of course it won't.  Need to omit the argument to reset it\n\t\t\t\tHelper.setLockTimeout( \"set lock wait\", connection, factory );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tHelper.setLockTimeout( (int) Math.ceil( (double) milliseconds / 1000), \"set lock wait %s\", connection, factory );\n\t\t\t}\n\t\t}\n\t}\n}\n","sourceCodeStart":175,"sourceCodeEnd":207,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/TransactSQLLockingSupport.java#L175-L207","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Use a real positive timeout in ms (SybaseImpl rounds up to seconds) or WAIT_FOREVER (-1); use 0 for no-wait (supported here)","Implement skip-locked semantics with native SQL appropriate to Sybase (e.g. READPAST-style behavior) instead of the timeout value","Check getSupportedLevel() (EXTENDED on Sybase) and never feed SKIP_LOCKED to connection-level timeouts","Remove -2 lock timeout hints from configuration shared across databases"],"exampleFix":"// before\nLockOptions options = new LockOptions(LockMode.PESSIMISTIC_WRITE).setTimeout(LockOptions.SKIP_LOCKED); // -2 -> throws\nsession.buildLockRequest(options).lock(entity);\n\n// after\nLockOptions options = new LockOptions(LockMode.PESSIMISTIC_WRITE).setTimeout(5000); // 5s wait\nsession.buildLockRequest(options).lock(entity);","handlingStrategy":"validation","validationCode":"int millis = lockOptions.getTimeOut();\nif (millis == Timeouts.SKIP_LOCKED_MILLI) {\n    lockOptions.setTimeOut(5000); // 'set lock wait' (seconds) cannot express skip-locked\n}","typeGuard":"static boolean acceptsConnectionTimeout(ConnectionLockTimeoutStrategy s, int millis) {\n    if (s.getSupportedLevel() == ConnectionLockTimeoutStrategy.Level.NONE) return false;\n    return millis != Timeouts.SKIP_LOCKED_MILLI;\n}","tryCatchPattern":"try {\n    session.buildLockRequest(lockOptions).lock(entity);\n} catch (HibernateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"skip-locked\")) {\n        lockOptions.setTimeout(5000);\n        session.buildLockRequest(lockOptions).lock(entity);\n    } else { throw e; }\n}","preventionTips":["Remember 'set lock wait' is seconds-based and cannot encode skip-locked on Sybase","Use no-wait (0) which Sybase accepts, or clause-level constructs for skip semantics","Keep lock timeout configuration per-dialect","Add Sybase to the databases covered by locking integration tests"],"tags":["sybase","pessimistic-locking","lock-timeout","skip-locked","hibernate"],"backgroundTag":"pessimistic-lock-timeout-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}