{"record":{"id":"4744e04d54526f8e","repo":"hibernate/hibernate-orm","slug":"jndi-name-could-not-be-resolved","errorCode":null,"errorMessage":"JNDI name [{}] could not be resolved","messagePattern":"JNDI name \\[(.+?)\\] could not be resolved","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"critical","filePath":"hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/DataSourceBasedMultiTenantConnectionProviderImpl.java","lineNumber":88,"sourceCode":"\t}\n\n\t@Override\n\tpublic void injectServices(@Nonnull ServiceRegistryImplementor serviceRegistry) {\n\t\tfinal var configurationService = serviceRegistry.requireService( ConfigurationService.class );\n\t\tfinal Object dataSourceConfigValue = configurationService.getSettings().get( DATASOURCE );\n\t\tif ( !(dataSourceConfigValue instanceof String configuredJndiName) ) {\n\t\t\tthrow new HibernateException( \"illegal value for configuration setting '\" + DATASOURCE + \"'\" );\n\t\t}\n\t\tjndiName = configuredJndiName;\n\n\t\tjndiService = serviceRegistry.getService( JndiService.class );\n\t\tif ( jndiService == null ) {\n\t\t\tthrow new HibernateException( \"Could not locate JndiService from DataSourceBasedMultiTenantConnectionProviderImpl\" );\n\t\t}\n\n\t\tfinal Object namedObject = jndiService.locate( this.jndiName );\n\t\tif ( namedObject == null ) {\n\t\t\tthrow new HibernateException( \"JNDI name [\" + this.jndiName + \"] could not be resolved\" );\n\t\t}\n\t\telse if ( namedObject instanceof DataSource datasource ) {\n\t\t\tfinal int loc = jndiName.lastIndexOf( '/' );\n\t\t\tbaseJndiNamespace = jndiName.substring( 0, loc );\n\t\t\tfinal String prefix = jndiName.substring( loc + 1);\n\t\t\ttenantIdentifierForAny = (T) prefix;\n\t\t\tdataSourceMap().put( tenantIdentifierForAny, datasource );\n\t\t}\n\t\telse if ( namedObject instanceof Context ) {\n\t\t\tbaseJndiNamespace = jndiName;\n\t\t\tfinal Object configuredTenantId =\n\t\t\t\t\tconfigurationService.getSettings().get( TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY );\n\t\t\ttenantIdentifierForAny = (T) configuredTenantId;\n\t\t\tif ( tenantIdentifierForAny == null ) {\n\t\t\t\tthrow new HibernateException( \"JNDI name named a Context, but tenant identifier to use for ANY was not specified\" );\n\t\t\t}\n\t\t}\n\t\telse {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/DataSourceBasedMultiTenantConnectionProviderImpl.java#L70-L106","documentation":"The JNDI name configured in hibernate.connection.datasource was handed to JndiService.locate() and the lookup returned null, meaning nothing is bound at that name in the reachable JNDI tree. Hibernate throws this immediately at bootstrap because the multi-tenant provider has no root object to derive per-tenant DataSources from.","triggerScenarios":"jndiService.locate(jndiName) returns null - name typo (java:/datasources/tenants vs java:datasources/tenants), the DataSource not deployed/bound, looking up in the wrong namespace, or JNDI environment pointing at the wrong InitialContext (remote vs local).","commonSituations":"DataSource defined in the app server but under a different JNDI name than configured; WildFly/Jetty/TomEE binding names that differ between versions (java:jboss/datasources/... vs java:/comp/env/...); integration tests with an empty embedded JNDI tree.","solutions":["Pre-verify the binding with a direct lookup: new InitialContext().lookup(\"<name>\") and fix the configured value to the exact bound name","Check the server's datasource definition (subsystem=datasources, server.xml Resource, etc.) and deploy/bind the resource","Align hibernate.jndi.* environment properties with the actual naming provider (local vs remote InitialContext)"],"exampleFix":"// before\n<property name=\"hibernate.connection.datasource\" value=\"java:/datasources/tenantRoot\"/> <!-- not bound -->\n\n// after (name matches the actual WildFly binding)\n<property name=\"hibernate.connection.datasource\" value=\"java:jboss/datasources/tenantRoot\"/>","handlingStrategy":"validation","validationCode":"// pre-flight the exact binding before Hibernate boots\nObject bound;\ntry {\n    bound = new InitialContext().lookup(jndiName);\n} catch (NamingException e) {\n    throw new IllegalStateException(\"Nothing bound at \" + jndiName, e);\n}\nif ( bound == null ) throw new IllegalStateException(\"JNDI returned null for \" + jndiName);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Externalize the JNDI name and verify it with a lookup in a deployment smoke test","Keep datasource JNDI names in server config and app config in one shared source to avoid drift"],"tags":["hibernate","jndi","multitenancy","datasource","lookup","bootstrap"],"backgroundTag":"jndi-lookup-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}