{"record":{"id":"4e1a0ff2c6548286","repo":"hibernate/hibernate-orm","slug":"illegal-attempt-to-get-lock-mode-for-a-procedure-c","errorCode":null,"errorMessage":"Illegal attempt to get lock mode for a procedure call","messagePattern":"Illegal attempt to get lock mode for a procedure call","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java","lineNumber":398,"sourceCode":"\t\tsuper.setTimeout( timeout );\n\t\treturn this;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ProcedureCallImplementor<R> setTimeout(@Nullable Timeout timeout) {\n\t\tcheckNotClosed();\n\t\tsuper.setTimeout( timeout );\n\t\treturn this;\n\t}\n\n\t@Override\n\t@Deprecated @SuppressWarnings(\"removal\")\n\t@Nullable\n\tpublic LockModeType getLockMode() {\n\t\t// the JPA spec requires IllegalStateException here, even\n\t\t// though it's logically an UnsupportedOperationException\n\t\tthrow new IllegalStateException( \"Illegal attempt to get lock mode for a procedure call\" );\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ProcedureCallImplementor<R> setFlushMode(@Nonnull FlushModeType flushModeType) {\n\t\tcheckNotClosed();\n\t\tsuper.setFlushMode( flushModeType );\n\t\treturn this;\n\t}\n\n\tpublic List<ResultSetMapping> getResultSetMappings() {\n\t\treturn resultSetMappings;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ProcedureCallImplementor<R> setCacheRetrieveMode(@Nonnull CacheRetrieveMode cacheRetrieveMode) {\n\t\tcheckNotClosed();","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/procedure/internal/ProcedureCallImpl.java#L380-L416","documentation":"The JPA specification requires Query.getLockMode() to throw IllegalStateException when the query is not a JPQL/Criteria selection query; ProcedureCallImpl follows the spec (the source comment notes the logically-fitting exception would be UnsupportedOperationException, but the spec wins). Any attempt to read the lock mode of a procedure call therefore fails.","triggerScenarios":"Calling getLockMode() on a StoredProcedureQuery/ProcedureCall — usually generic code that snapshots a query's lock state for logging, auditing, or metrics.","commonSituations":"Observability wrappers that record lock modes of all executed queries; assertion helpers in tests that inspect query configuration; tracing interceptors around em.createQuery calls.","solutions":["Guard with instanceof StoredProcedureQuery/ProcedureCall before calling getLockMode().","For audit data, read getHints() instead, which works on all query types.","Push lock-mode introspection behind a helper that only accepts SelectionQuery."],"exampleFix":"// before\nLockModeType mode = query.getLockMode(); // query is a StoredProcedureQuery -> throws\n\n// after\nLockModeType mode = (query instanceof StoredProcedureQuery)\n        ? null  // locking is not applicable to procedure calls\n        : query.getLockMode();","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean supportsLockMode(jakarta.persistence.Query q) {\n    return !( q instanceof StoredProcedureQuery );\n}","tryCatchPattern":"try {\n    LockModeType mode = q.getLockMode();\n} catch (IllegalStateException e) {\n    // spec-required: procedure calls have no lock mode\n}","preventionTips":["Guard getLockMode() with instanceof StoredProcedureQuery in logging/audit wrappers.","Use getHints() for uniform audit data across query types."],"tags":["hibernate","stored-procedure","locking","jpa"],"backgroundTag":"locking-not-supported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}