{"record":{"id":"df3076f1adf061e7","repo":"hibernate/hibernate-orm","slug":"connection-lock-timeout-does-not-accept-skip-locke-df3076","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/lock/internal/GaussDBLockingSupport.java","lineNumber":130,"sourceCode":"\tprivate static int getTimeout(String value, int unitLength) {\n\t\tfinal int number;\n\t\ttry {\n\t\t\tnumber = Integer.parseInt( value.substring( 0, value.length() - unitLength ) );\n\t\t}\n\t\tcatch (NumberFormatException e) {\n\t\t\tthrow new RuntimeException( e );\n\t\t}\n\t\treturn number;\n\t}\n\n\t@Override\n\tpublic void setLockTimeout(Timeout timeout, Connection connection, SessionFactoryImplementor factory) {\n\t\tHelper.setLockTimeout(\n\t\t\t\ttimeout,\n\t\t\t\t(t) -> {\n\t\t\t\t\tfinal int milliseconds = timeout.milliseconds();\n\t\t\t\t\tif ( milliseconds == SKIP_LOCKED_MILLI ) {\n\t\t\t\t\t\tthrow new HibernateException( \"Connection lock-timeout does not accept skip-locked\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( milliseconds == NO_WAIT_MILLI ) {\n\t\t\t\t\t\tthrow new HibernateException( \"Connection lock-timeout does not accept no-wait\" );\n\t\t\t\t\t}\n\t\t\t\t\treturn milliseconds == WAIT_FOREVER_MILLI\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: milliseconds;\n\t\t\t\t},\n\t\t\t\t\"set local lockwait_timeout = %s\",\n\t\t\t\tconnection,\n\t\t\t\tfactory\n\t\t);\n\t}\n}\n","sourceCodeStart":112,"sourceCodeEnd":146,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/lock/internal/GaussDBLockingSupport.java#L112-L146","documentation":"GaussDBLockingSupport implements the connection-level lock timeout by executing 'set local lockwait_timeout = <ms>' before the locking statement. Hibernate's Timeout API encodes skip-locked as the sentinel value SKIP_LOCKED_MILLI (not a duration); since lockwait_timeout is a plain millisecond setting that cannot express 'skip locked', setLockTimeout throws this HibernateException ('Connection lock-timeout does not accept skip-locked').","triggerScenarios":"On GaussDB/openGauss, setting a lock timeout of Timeout.skipLocked() - e.g. selectionQuery.setLockTimeout(Timeout.skipLocked()) or the equivalent 'jakarta.persistence.lock.timeout' = -2 (LockOptions.SKIP_LOCKED) when the dialect applies it at the connection level. The LockTimeoutHandler calls GaussDBLockingSupport.setLockTimeout, which rejects the sentinel milliseconds value.","commonSituations":"Queue/batch-processing code using SKIP LOCKED semantics ported to GaussDB; setting the JPA lock.timeout hint to -2 globally; switching dialects from PostgreSQL (which translates skip-locked into lock_timeout handling differently) to GaussDB.","solutions":["Do not request skip-locked via the lock timeout on GaussDB: use Timeout.milliseconds(n) or Timeout.waitForever() instead.","Get SKIP LOCKED semantics through row-level locking in the query itself (setLockMode / LockOptions with skip-locked follow-on locking) rather than the connection lock-timeout.","Remove the 'jakarta.persistence.lock.timeout' = -2 hint from the query/entity-manager properties on this database.","Catch the HibernateException and degrade to a bounded wait timeout."],"exampleFix":"// before - throws on GaussDB\nquery.setLockTimeout(Timeout.skipLocked());\n\n// after - bounded wait, or rely on query lock options\nquery.setLockTimeout(Timeout.milliseconds(5000));","handlingStrategy":"validation","validationCode":"boolean gauss = sessionFactory.getJdbcServices().getDialect() instanceof org.hibernate.community.dialect.GaussDBDialect;\nTimeout t = gauss && requested.isSkipLocked()\n        ? Timeout.milliseconds(5000)  // substitute a bounded wait\n        : requested;","typeGuard":"static boolean usableAsConnectionLockTimeout(Timeout t) {\n    // reject the sentinels that are not durations\n    return !t.isSkipLocked() && !t.isNoWait();\n}","tryCatchPattern":"try {\n    query.setLockTimeout(Timeout.skipLocked()).getResultList();\n} catch (HibernateException e) {\n    if (e.getMessage().contains(\"skip-locked\")) {\n        query.setLockTimeout(Timeout.milliseconds(5000)).getResultList(); // graceful degrade\n    } else throw e;\n}","preventionTips":["Do not set lock.timeout hints to -2 (skip-locked) or 0 (no-wait) on GaussDB","Use positive millisecond timeouts for connection-level locking","Encapsulate lock-timeout selection per dialect in one utility"],"tags":["gaussdb","locking","pessimistic-lock","lock-timeout","skip-locked","hibernate-exception"],"backgroundTag":"unsupported-lock-timeout","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}