{"record":{"id":"246202805a4d7268","repo":"hibernate/hibernate-orm","slug":"jndi-name-named-a-context-but-tenant-identifier-t","errorCode":null,"errorMessage":"JNDI name named a Context, but tenant identifier to use for ANY was not specified","messagePattern":"JNDI name named a Context, but tenant identifier to use for ANY was not specified","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"critical","filePath":"hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/DataSourceBasedMultiTenantConnectionProviderImpl.java","lineNumber":103,"sourceCode":"\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 {\n\t\t\tthrow new HibernateException(\n\t\t\t\t\t\"Unknown object type [\" + namedObject.getClass().getName() +\n\t\t\t\t\t\"] found in JNDI location [\" + this.jndiName + \"]\"\n\t\t\t);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void stop() {\n\t\tdataSourceMap.clear();\n\t}\n\n\t@Override\n\tpublic DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {\n\t\treturn new DatabaseConnectionInfoImpl(","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/DataSourceBasedMultiTenantConnectionProviderImpl.java#L85-L121","documentation":"The configured JNDI name resolved to a javax.naming.Context (a namespace expected to contain one DataSource per tenant) rather than a single DataSource. In that mode the provider needs to know which tenant identifier to use for 'any' (non-tenant-specific) connection requests; it reads MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY ('hibernate.multi_tenant.datasource.identifier_for_any') and throws when it is not set.","triggerScenarios":"hibernate.connection.datasource points at a Context node (e.g. java:/datasources holding hibernate/db2/postgres children) while 'hibernate.multi_tenant.datasource.identifier_for_any' is absent from the settings map.","commonSituations":"Multitenant setups where each tenant DataSource is bound under a common JNDI namespace; the developer forgot the identifier_for_any property or used a stale property name from an older Hibernate version.","solutions":["Add the property: hibernate.multi_tenant.datasource.identifier_for_any=<tenantId> (the id whose DataSource serves 'any' connections)","Alternatively point hibernate.connection.datasource directly at one concrete DataSource instead of the parent Context, letting the provider derive base namespace and ANY identifier from the name","Verify the chosen tenant id actually has a DataSource bound under the namespace"],"exampleFix":"// before\nsettings.put(\"hibernate.connection.datasource\", \"java:/datasources\"); // resolves to Context\n// -> JNDI name named a Context, but tenant identifier to use for ANY was not specified\n\n// after\nsettings.put(\"hibernate.connection.datasource\", \"java:/datasources\");\nsettings.put(MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY, \"db2\");","handlingStrategy":"validation","validationCode":"// if the JNDI target is a Context namespace, require the ANY-tenant identifier up front\nObject target = new InitialContext().lookup(jndiName);\nif ( target instanceof Context\n        && settings.get(MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY) == null ) {\n    throw new ConfigurationException(\n        \"Set hibernate.multi_tenant.datasource.identifier_for_any when the datasource name is a Context\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Document the pairing: JNDI Context name + identifier_for_any must appear together","Cover multitenant bootstrap config with a unit test that builds the service registry"],"tags":["hibernate","multitenancy","jndi","configuration","context"],"backgroundTag":"missing-configuration-property","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}