hibernate/hibernate-orm · critical · HibernateException

JNDI name named a Context, but tenant identifier to use for

Error message

JNDI name named a Context, but tenant identifier to use for ANY was not specified

What it means

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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/spi/DataSourceBasedMultiTenantConnectionProviderImpl.java:103

		final Object namedObject = jndiService.locate( this.jndiName );
		if ( namedObject == null ) {
			throw new HibernateException( "JNDI name [" + this.jndiName + "] could not be resolved" );
		}
		else if ( namedObject instanceof DataSource datasource ) {
			final int loc = jndiName.lastIndexOf( '/' );
			baseJndiNamespace = jndiName.substring( 0, loc );
			final String prefix = jndiName.substring( loc + 1);
			tenantIdentifierForAny = (T) prefix;
			dataSourceMap().put( tenantIdentifierForAny, datasource );
		}
		else if ( namedObject instanceof Context ) {
			baseJndiNamespace = jndiName;
			final Object configuredTenantId =
					configurationService.getSettings().get( TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY );
			tenantIdentifierForAny = (T) configuredTenantId;
			if ( tenantIdentifierForAny == null ) {
				throw new HibernateException( "JNDI name named a Context, but tenant identifier to use for ANY was not specified" );
			}
		}
		else {
			throw new HibernateException(
					"Unknown object type [" + namedObject.getClass().getName() +
					"] found in JNDI location [" + this.jndiName + "]"
			);
		}
	}

	@Override
	public void stop() {
		dataSourceMap.clear();
	}

	@Override
	public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
		return new DatabaseConnectionInfoImpl(

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add the property: hibernate.multi_tenant.datasource.identifier_for_any=<tenantId> (the id whose DataSource serves 'any' connections)
  2. 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
  3. Verify the chosen tenant id actually has a DataSource bound under the namespace

Example fix

// before
settings.put("hibernate.connection.datasource", "java:/datasources"); // resolves to Context
// -> JNDI name named a Context, but tenant identifier to use for ANY was not specified

// after
settings.put("hibernate.connection.datasource", "java:/datasources");
settings.put(MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY, "db2");
Defensive patterns

Strategy: validation

Validate before calling

// if the JNDI target is a Context namespace, require the ANY-tenant identifier up front
Object target = new InitialContext().lookup(jndiName);
if ( target instanceof Context
        && settings.get(MultiTenancySettings.TENANT_IDENTIFIER_TO_USE_FOR_ANY_KEY) == null ) {
    throw new ConfigurationException(
        "Set hibernate.multi_tenant.datasource.identifier_for_any when the datasource name is a Context");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/246202805a4d7268. Report an issue: GitHub.