hibernate/hibernate-orm · critical · HibernateException

Unknown object type [{}] found in JNDI location [{}]

Error message

Unknown object type [{}] found in JNDI location [{}]

What it means

The object bound at the configured JNDI name was successfully located, but it is neither a javax.sql.DataSource nor a javax.naming.Context. DataSourceBasedMultiTenantConnectionProviderImpl only understands these two shapes (a DataSource to treat as the 'any' tenant plus a namespace prefix, or a Context of per-tenant DataSources), so any other type is rejected with the bound object's class name.

Source

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

		}
		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(
				null,
				null,
				null,
				dialect.getClass(),

View on GitHub (pinned to fad1729dce)

Solutions

  1. Rebind or point the configuration at an object that is a javax.sql.DataSource or a naming Context of DataSources
  2. Inspect what is actually bound: Object o = new InitialContext().lookup(name); System.out.println(o.getClass())
  3. If a Reference/proxy is returned during deployment ordering, ensure the datasource is fully started before Hibernate boots

Example fix

// before: bound a String reference
ctx.rebind("java:/datasources/any", "jdbc/mydb"); // String -> Unknown object type

// after: bind the DataSource itself
ctx.rebind("java:/datasources/any", tenantDataSource);
Defensive patterns

Strategy: validation

Validate before calling

// assert the bound object has one of the two accepted shapes before bootstrap
Object o = new InitialContext().lookup(jndiName);
if ( !(o instanceof DataSource) && !(o instanceof Context) ) {
    throw new ConfigurationException(
        "Expected DataSource or Context at " + jndiName + " but found " + o.getClass().getName());
}

Prevention

When it happens

Trigger: jndiService.locate(jndiName) returns e.g. a String, java.net.URL, ConnectionFactory, Reference, or a lazy proxy that is neither DataSource nor Context - common when the name targets the wrong subnode or a non-JDBC resource.

Common situations: Pointing hibernate.connection.datasource at a JCA resource, a JMS connection factory, or an env-entry by mistake; bindings that return javax.naming.Reference before the resource is fully deployed; copy-paste of the wrong JNDI name.

Related errors


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