{"record":{"id":"c9ebf22a165f92cf","repo":"hibernate/hibernate-orm","slug":"row-level-security-enabled-but-no-tenant-identifi","errorCode":null,"errorMessage":"Row-level security enabled, but no tenant identifier specified","messagePattern":"Row-level security enabled, but no tenant identifier specified","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java","lineNumber":1268,"sourceCode":"\tpublic void afterTransactionBegin() {\n\t\tsetUpRowLevelSecurity();\n\t}\n\n\tprivate RowLevelSecurity getRowLevelSecurity() {\n\t\treturn getJdbcServices().getDialect().getRowLevelSecurity();\n\t}\n\n\tprivate void setUpRowLevelSecurity() {\n\t\tif ( rowLevelSecurityEnabled ) {\n\t\t\tsetUpRowLevelSecurity( getJdbcCoordinator().getLogicalConnection().getPhysicalConnection() );\n\t\t}\n\t}\n\n\tprivate void setUpRowLevelSecurity(Connection connection) {\n\t\tif ( rowLevelSecurityEnabled ) {\n\t\t\tfinal Object tenantIdentifier = getTenantIdentifierValue();\n\t\t\tif ( tenantIdentifier == null ) {\n\t\t\t\tthrow new HibernateException( \"Row-level security enabled, but no tenant identifier specified\" );\n\t\t\t}\n\n\t\t\tif ( !useDatabaseUserForRowLevelSecurity() ) {\n\t\t\t\tfinal var resolver = factory.getCurrentTenantIdentifierResolver();\n\t\t\t\tfinal boolean root = resolver != null && resolver.isRoot( tenantIdentifier );\n\t\t\t\ttry {\n\t\t\t\t\tgetRowLevelSecurity()\n\t\t\t\t\t\t\t.setTenantIdentifier( connection, getTenantIdentifier(), root );\n\t\t\t\t}\n\t\t\t\tcatch (SQLException e) {\n\t\t\t\t\tthrow getJdbcServices().getSqlExceptionHelper()\n\t\t\t\t\t\t\t.convert( e, \"Unable to set row-level security tenant identifier\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate boolean useDatabaseUserForRowLevelSecurity() {","sourceCodeStart":1250,"sourceCodeEnd":1286,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java#L1250-L1286","documentation":"Row-level security is switched on for this factory (SessionFactoryOptions rowLevelSecurityEnabled), so when a session first uses its physical connection setUpRowLevelSecurity() must bind the tenant onto it (RowLevelSecurity.setTenantIdentifier or a dedicated DB user in user-mode). getTenantIdentifierValue() returned null, so the connection cannot be pinned to a tenant partition and Hibernate aborts rather than run with unrestricted row visibility.","triggerScenarios":"Enabling the row-level security setting (e.g., hibernate.row_level_security) while opening sessions/EntityManagers without a tenant identifier and without a CurrentTenantIdentifierResolver that yields one; typically fails on the first statement that acquires the physical connection.","commonSituations":"Adopting Hibernate 7 row-level security (PostgreSQL/Oracle RLS integration) without porting over the tenant-context infrastructure; system/background sessions that have no tenant; resolver wired only for web request threads.","solutions":["Provide the tenant for every session exactly as for multi-tenancy: withOptions().tenantIdentifier(...) on open, or a CurrentTenantIdentifierResolver that always resolves a value (see error 1540).","If row-level security was enabled by accident or is not needed for this factory, remove the setting.","In database-user mode, also verify the tenant-to-user mapping exists so useDatabaseUserForRowLevelSecurity() can switch users."],"exampleFix":"// before\nSession s = sf.openSession(); // row-level security enabled, no tenant\ns.find(Customer.class, 1L); // HibernateException\n// after\nSession s = sf.withOptions().tenantIdentifier(tenantContext.get()).openSession();","handlingStrategy":"validation","validationCode":"Object tenant = tenantContext.get();\nif (tenant == null) {\n    throw new IllegalStateException(\"Row-level security requires a tenant on every session\");\n}\ntry (Session s = sf.withOptions().tenantIdentifier(tenant).openSession()) { ... }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reuse the multi-tenancy tenant infrastructure when enabling row-level security","Cover system jobs with an explicit root/system tenant if the resolver supports isRoot()","Add a startup self-check that opens and queries one session per configured mode"],"tags":["hibernate","row-level-security","multi-tenancy","tenant-id","connection"],"backgroundTag":"missing-tenant-identifier","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}