{"record":{"id":"689cedcc5f66d319","repo":"hibernate/hibernate-orm","slug":"connection-lock-timeout-does-not-accept-skip-locke","errorCode":null,"errorMessage":"Connection lock-timeout does not accept skip-locked","messagePattern":"Connection lock-timeout does not accept skip-locked","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixLockingSupport.java","lineNumber":85,"sourceCode":"\t\t\t\t\"select scs_lockmode from sysmaster:syssqlcurses where scs_sessionid = dbinfo('sessionid')\",\n\t\t\t\t(resultSet) -> {\n\t\t\t\t\tfinal int seconds = resultSet.getInt( 1 );\n\t\t\t\t\treturn switch ( seconds ) {\n\t\t\t\t\t\tcase -1 -> Timeouts.WAIT_FOREVER;\n\t\t\t\t\t\tcase 0 -> Timeouts.NO_WAIT;\n\t\t\t\t\t\tdefault -> Timeout.seconds( seconds );\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tconnection,\n\t\t\t\tfactory\n\t\t);\n\t}\n\n\t@Override\n\tpublic void setLockTimeout(Timeout timeout, Connection connection, SessionFactoryImplementor factory) {\n\t\tfinal int milliseconds = timeout.milliseconds();\n\t\tif ( milliseconds == SKIP_LOCKED_MILLI ) {\n\t\t\tthrow new HibernateException( \"Connection lock-timeout does not accept skip-locked\" );\n\t\t}\n\t\tif ( milliseconds == WAIT_FOREVER_MILLI ) {\n\t\t\tHelper.setLockTimeout(\n\t\t\t\t\t\"set lock mode to wait\",\n\t\t\t\t\tconnection,\n\t\t\t\t\tfactory\n\t\t\t);\n\t\t}\n\t\telse if ( milliseconds == NO_WAIT_MILLI ) {\n\t\t\tHelper.setLockTimeout(\n\t\t\t\t\t\"set lock mode to not wait\",\n\t\t\t\t\tconnection,\n\t\t\t\t\tfactory\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\tHelper.setLockTimeout(\n\t\t\t\t\t(int) Math.ceil( (double) milliseconds / 1000),","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixLockingSupport.java#L67-L103","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove the skip-locked option on Informix: use LockOptions.NO_WAIT or a short wait timeout for polling loops","Implement the queue pattern without pessimistic skip-locked: optimistic @Version-based claiming (UPDATE ... WHERE status=...) or a database-native mechanism","Gate locking strategy per database: check the dialect before applying skip-locked options"],"exampleFix":"// before\nLockOptions opts = new LockOptions(LockMode.PESSIMISTIC_WRITE).setSkipLocked(true);\nsession.find(Item.class, id, opts); // -> HibernateException on Informix\n\n// after - poll with no-wait and retry on cannot-acquire\nLockOptions opts = new LockOptions(LockMode.PESSIMISTIC_WRITE)\n        .setTimeOut(LockOptions.NO_WAIT);\ntry { session.find(Item.class, id, opts); }\ncatch (PessimisticLockException e) { /* another worker holds it */ }","handlingStrategy":"validation","validationCode":"boolean wantSkipLocked = /* requested by caller */;\nif ( session.getJdbcServices().getDialect() instanceof InformixDialect && wantSkipLocked ) {\n    // Informix: no connection-level skip-locked; degrade to NO_WAIT polling\n    lockOptions.setTimeOut(LockOptions.NO_WAIT);\n    lockOptions.setSkipLocked(false);\n}","typeGuard":"static boolean isInformix(Dialect d) { return d instanceof InformixDialect; }","tryCatchPattern":"try {\n    session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_WRITE).setSkipLocked(true))\n           .lock(item);\n} catch (HibernateException e) {\n    if ( String.valueOf(e.getMessage()).contains(\"skip-locked\") ) {\n        // fall back to optimistic claiming: UPDATE ... WHERE status = 'NEW'\n    }\n    throw e;\n}","preventionTips":["Do not set jakarta.persistence.lock.timeout=-2 globally in persistence.xml - it applies to every database profile","Centralize lock acquisition behind a LockPolicy that is configured per dialect","Prefer optimistic @Version claiming for work queues; it is portable and avoids connection-level lock timeouts"],"tags":["hibernate","informix","pessimistic-locking","skip-locked","lock-timeout"],"backgroundTag":"skip-locked-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}