hibernate/hibernate-orm · critical · HibernateException

illegal value for configuration setting 'hibernate.connectio

Error message

illegal value for configuration setting 'hibernate.connection.datasource'

What it means

DataSourceBasedMultiTenantConnectionProviderImpl.injectServices reads the setting hibernate.connection.datasource and requires it to be a String holding a JNDI name, because this provider locates per-tenant DataSources through JNDI. If the value is absent or not a String (e.g. a DataSource instance was placed in the settings map), Hibernate throws HibernateException with this message during ServiceRegistry injection at bootstrap.

Source

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

	protected DataSource selectDataSource(T tenantIdentifier) {
		DataSource dataSource = dataSourceMap().get( tenantIdentifier );
		if ( dataSource == null ) {
			dataSource = (DataSource) jndiService.locate( baseJndiNamespace + '/' + tenantIdentifier );
			dataSourceMap().put( tenantIdentifier, dataSource );
		}
		return dataSource;
	}

	private Map<T, DataSource> dataSourceMap() {
		return dataSourceMap;
	}

	@Override
	public void injectServices(@Nonnull ServiceRegistryImplementor serviceRegistry) {
		final var configurationService = serviceRegistry.requireService( ConfigurationService.class );
		final Object dataSourceConfigValue = configurationService.getSettings().get( DATASOURCE );
		if ( !(dataSourceConfigValue instanceof String configuredJndiName) ) {
			throw new HibernateException( "illegal value for configuration setting '" + DATASOURCE + "'" );
		}
		jndiName = configuredJndiName;

		jndiService = serviceRegistry.getService( JndiService.class );
		if ( jndiService == null ) {
			throw new HibernateException( "Could not locate JndiService from DataSourceBasedMultiTenantConnectionProviderImpl" );
		}

		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 );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Set the property to the JNDI name string, e.g. hibernate.connection.datasource=java:/datasources/tenants
  2. If you do not use JNDI, replace this provider with a custom MultiTenantConnectionProvider that maps tenant identifiers to DataSource instances directly
  3. Verify no code overrides the property with a non-String value after configuration merging

Example fix

// before
Map<String,Object> settings = new HashMap<>();
settings.put(AvailableSettings.DATASOURCE, myDataSourceObject); // not a String -> HibernateException

// after
settings.put(AvailableSettings.DATASOURCE, "java:/datasources/tenants");
Defensive patterns

Strategy: validation

Validate before calling

// validate before building the SessionFactory
Object v = settings.get(AvailableSettings.DATASOURCE);
if ( providerIsDataSourceBased && !(v instanceof String jndiName) ) {
    throw new IllegalArgumentException(
        "hibernate.connection.datasource must be a JNDI name String, got: " + v);
}

Try / catch

try {
    sf = builder.build();
} catch (HibernateException e) {
    if ( e.getMessage() != null && e.getMessage().contains("hibernate.connection.datasource") ) {
        throw new ConfigurationException("Fix hibernate.connection.datasource to a JNDI name String", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Configuring hibernate.multiTenancy with DataSourceBasedMultiTenantConnectionProviderImpl while AvailableSettings.DATASOURCE ('hibernate.connection.datasource') is missing, or is a javax.sql.DataSource object, Integer, or any non-String value in the properties map passed to sessionFactory building.

Common situations: Spring Boot or programmatic bootstrap putting a DataSource bean into hibernate properties instead of a JNDI name; copy-pasted persistence.xml where <jta-data-source>/<non-jta-data-source> semantics differ; migrating a working single-tenant JNDI setup where the property was omitted.

Related errors


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