{"record":{"id":"dc873c32ab2bfbcf","repo":"hibernate/hibernate-orm","slug":"write-is-not-a-valid-lockmode-as-an-argument","errorCode":null,"errorMessage":"WRITE is not a valid LockMode as an argument","messagePattern":"WRITE is not a valid LockMode as an argument","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/LockMode.java","lineNumber":345,"sourceCode":"\t/**\n\t * @return an instance of {@link LockOptions} with this lock mode, and\n\t *         all other settings defaulted.\n\t *\n\t * @deprecated With no replacement; {@linkplain LockOptions} is no longer considered an API.\n\t */\n\t@Deprecated(since = \"7\", forRemoval = true)\n\tpublic LockOptions toLockOptions() {\n\t\treturn switch (this) {\n\t\t\tcase NONE -> new LockOptions();\n\t\t\tcase READ -> new LockOptions( READ );\n\t\t\tcase OPTIMISTIC -> new LockOptions( OPTIMISTIC );\n\t\t\tcase OPTIMISTIC_FORCE_INCREMENT -> new LockOptions( OPTIMISTIC_FORCE_INCREMENT );\n\t\t\tcase UPGRADE_NOWAIT -> new LockOptions( PESSIMISTIC_WRITE, NO_WAIT_MILLI, PessimisticLockScope.NORMAL, Locking.FollowOn.ALLOW );\n\t\t\tcase UPGRADE_SKIPLOCKED -> new LockOptions( PESSIMISTIC_WRITE, SKIP_LOCKED_MILLI, PessimisticLockScope.NORMAL, Locking.FollowOn.ALLOW );\n\t\t\tcase PESSIMISTIC_READ -> new LockOptions( PESSIMISTIC_READ );\n\t\t\tcase PESSIMISTIC_WRITE -> new LockOptions( PESSIMISTIC_WRITE );\n\t\t\tcase PESSIMISTIC_FORCE_INCREMENT -> new LockOptions( PESSIMISTIC_FORCE_INCREMENT );\n\t\t\tcase WRITE -> throw new UnsupportedOperationException( \"WRITE is not a valid LockMode as an argument\" );\n\t\t};\n\t}\n\n\tpublic boolean isPessimistic() {\n\t\treturn this == PESSIMISTIC_READ\n\t\t\t|| this == PESSIMISTIC_WRITE\n\t\t\t|| this == PESSIMISTIC_FORCE_INCREMENT\n\t\t\t|| this == UPGRADE_NOWAIT\n\t\t\t|| this == UPGRADE_SKIPLOCKED;\n\t}\n}\n","sourceCodeStart":327,"sourceCodeEnd":357,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/LockMode.java#L327-L357","documentation":"LockMode.WRITE is an internal, legacy lock mode that Hibernate itself historically applied to entities while flushing changes (to force a version increment). It was never meant to be requested by callers, so the deprecated LockMode.toLockOptions() switch (LockMode.java:345) has no LockOptions equivalent for it and throws UnsupportedOperationException instead of silently producing a wrong lock. Any API path that converts a caller-supplied LockMode into LockOptions hits this guard.","triggerScenarios":"Calling LockMode.WRITE.toLockOptions() directly, or passing LockMode.WRITE to an API that internally converts LockMode to LockOptions (e.g. session.get()/load() overloads or buildLockRequest helpers that accept a LockMode and translate it). Generic code that iterates all LockMode.values() and converts each one will also land on the WRITE case.","commonSituations":"Code migrated verbatim from Hibernate 2.x/3.x where LockMode.WRITE (or its predecessor LockMode.UPGRADE usage patterns) appeared in tutorials; copy-pasted locking snippets; test utilities that exercise every LockMode constant; upgrading to Hibernate 6/7 where toLockOptions() was introduced with this guard.","solutions":["Replace LockMode.WRITE with LockMode.PESSIMISTIC_FORCE_INCREMENT if you wanted the write-triggered version bump, or LockMode.PESSIMISTIC_WRITE for a plain SELECT ... FOR UPDATE","If you only need an immediate pessimistic lock, use session.buildLockRequest(LockOptions) (or JPA LockModeType.PESSIMISTIC_WRITE with EntityManager.lock/find) instead of converting a LockMode","Grep the codebase for LockMode.WRITE and remove/replace every use; it is internal-only","If a generic LockMode-to-LockOptions conversion is unavoidable, special-case WRITE by rejecting it with your own IllegalArgumentException before calling toLockOptions()"],"exampleFix":"// before\nLockOptions options = LockMode.WRITE.toLockOptions();\nsession.buildLockRequest(options).lock(entity);\n\n// after - request a real database lock instead of the internal WRITE mode\nsession.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_WRITE)).lock(entity);","handlingStrategy":"validation","validationCode":"// before any LockMode -> LockOptions conversion\nstatic LockOptions request(LockMode mode) {\n    if (mode == LockMode.WRITE) {\n        throw new IllegalArgumentException(\n            \"LockMode.WRITE is internal-only; use PESSIMISTIC_WRITE or PESSIMISTIC_FORCE_INCREMENT\");\n    }\n    return mode.toLockOptions();\n}","typeGuard":"static boolean isRequestableLockMode(LockMode mode) {\n    return mode != null && mode != LockMode.WRITE;\n}","tryCatchPattern":"try {\n    options = mode.toLockOptions();\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"not a valid LockMode\")) {\n        throw new IllegalArgumentException(\"Invalid lock mode requested: \" + mode, e);\n    }\n    throw e;\n}","preventionTips":["Grep for LockMode.WRITE and remove every occurrence; treat it as an Hibernate-internal constant","Centralize locking decisions in one helper that only accepts requestable modes","When migrating pre-Hibernate-4 code, map legacy WRITE to PESSIMISTIC_FORCE_INCREMENT or PESSIMISTIC_WRITE explicitly"],"tags":["locking","lock-mode","deprecated-api","migration","hibernate"],"backgroundTag":"invalid-lock-mode","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}