quarkusio/quarkus · error · IllegalStateException
Unexpected multitenancy strategy:
Error message
Unexpected multitenancy strategy:
What it means
DataSourceTenantConnectionResolver.resolve() handles only the DATABASE and SCHEMA multitenancy strategies; any other MultiTenancyStrategy value (e.g. NONE or DISCRIMINATOR) reaching this resolver is a configuration/programming error and throws IllegalStateException.
Source
Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/DataSourceTenantConnectionResolver.java:59
this.dataSourceName = dataSourceName;
this.multiTenancyStrategy = multiTenancyStrategy;
}
@Override
public ConnectionProvider resolve(String tenantId) {
LOG.debugv("resolve((persistenceUnitName={0}, tenantIdentifier={1})", persistenceUnitName, tenantId);
LOG.debugv("multitenancy strategy: {0}", multiTenancyStrategy);
AgroalDataSource dataSource = tenantDataSource(dataSourceName, tenantId, multiTenancyStrategy);
if (dataSource == null) {
throw new IllegalStateException(
String.format(Locale.ROOT, "No instance of datasource found for persistence unit '%1$s' and tenant '%2$s'",
persistenceUnitName, tenantId));
}
return switch (multiTenancyStrategy) {
case DATABASE -> new QuarkusConnectionProvider(dataSource);
case SCHEMA -> new SchemaTenantConnectionProvider(tenantId, dataSource);
default -> throw new IllegalStateException("Unexpected multitenancy strategy: " + multiTenancyStrategy);
};
}
private static AgroalDataSource tenantDataSource(Optional<String> dataSourceName, String tenantId,
MultiTenancyStrategy strategy) {
return switch (strategy) {
case DATABASE -> Arc.container().instance(AgroalDataSource.class, new DataSource.DataSourceLiteral(tenantId)).get();
// The datasource name should always be present when using a multi-tenancy other than DATABASE;
// we perform checks in HibernateOrmProcessor during the build.
case SCHEMA -> getDataSource(dataSourceName.get());
default -> throw new IllegalStateException("Unexpected multitenancy strategy: " + strategy);
};
}
private static AgroalDataSource getDataSource(String dataSourceName) {
return Arc.container().instance(AgroalDataSource.class, AgroalDataSourceUtil.qualifier(dataSourceName)).get();
}
View on GitHub (pinned to e1c734241f)
Solutions
- Set quarkus.hibernate-orm.multitenant=database or schema to match your TenantConnectionResolver
- Remove/don't register a TenantConnectionResolver if you use DISCRIMINATOR strategy (implement TenantIdBinder instead)
- Verify only one multitenancy strategy applies per persistence unit and the resolver matches it
Example fix
// before // resolver registered, multitenant not set -> strategy NONE -> throws // after (application.properties) quarkus.hibernate-orm.multitenant=database
Defensive patterns
Strategy: validation
Validate before calling
MultiTenancyStrategy s = /* resolved strategy */;
if (s != MultiTenancyStrategy.DATABASE && s != MultiTenancyStrategy.SCHEMA) {
throw new IllegalStateException("TenantConnectionResolver requires database/schema strategy, got " + s);
} Try / catch
try {
return resolver.resolve(tenantId);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Unexpected multitenancy strategy")) {
Log.error("Set quarkus.hibernate-orm.multitenant=database|schema");
}
throw e;
} Prevention
- Always set quarkus.hibernate-orm.multitenant when registering a TenantConnectionResolver
- Use TenantIdBinder for discriminator-based multitenancy, not a connection resolver
- Document which strategy each persistence unit uses
When it happens
Trigger: The resolver bean is instantiated/invoked while the persistence unit's MultiTenancyStrategy is something other than DATABASE or SCHEMA — e.g. multitenancy enabled inconsistently, a TenantConnectionResolver is registered but the strategy resolved to NONE/DISCRIMINATOR, or strategy enum changes between build and runtime.
Common situations: Registering a TenantConnectionResolver while using discriminator-column multitenancy; a custom resolver wired into a PU that isn't configured as multitenant (strategy NONE); custom code constructing the resolver with a stale strategy.
Related errors
- Weigher class '<className>' must implement com.github.benman
- Invalid ORM compatibility version: %1$s. Valid versions are:
- The 'quarkus.hibernate-orm.mapping.format.global' configurat
- No instance of datasource found for persistence unit '%1$s'
- Method 'TenantResolver.resolveTenantId()' returned a null va
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/cf6bbb8b57935654.
Report an issue: GitHub.