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

  1. Set quarkus.hibernate-orm.multitenant=database or schema to match your TenantConnectionResolver
  2. Remove/don't register a TenantConnectionResolver if you use DISCRIMINATOR strategy (implement TenantIdBinder instead)
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/cf6bbb8b57935654. Report an issue: GitHub.