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
- Set the property to the JNDI name string, e.g. hibernate.connection.datasource=java:/datasources/tenants
- If you do not use JNDI, replace this provider with a custom MultiTenantConnectionProvider that maps tenant identifiers to DataSource instances directly
- 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
- Never put a DataSource object into hibernate.connection.datasource; that setting is JNDI-name-only in Hibernate
- Validate all String-typed Hibernate settings in one startup check before EntityManagerFactory creation
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
- JNDI name [{}] could not be resolved
- Could not locate JndiService from DataSourceBasedMultiTenant
- JNDI name named a Context, but tenant identifier to use for
- Unknown object type [{}] found in JNDI location [{}]
- Unable to access TransactionManager or UserTransaction to ma
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b720c8f3f7eb7864.
Report an issue: GitHub.