quarkusio/quarkus · error · IllegalStateException
Method 'TenantConnectionResolver.resolve(String)' returned a
Error message
Method 'TenantConnectionResolver.resolve(String)' returned a null value. This violates the contract of the interface!
What it means
The contract of TenantConnectionResolver.resolve(String) requires a non-null ConnectionProvider. Quarkus throws IllegalStateException when a registered resolver returns null for the given tenant identifier.
Source
Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateMultiTenantConnectionProvider.java:97
private static ConnectionProvider resolveConnectionProvider(String persistenceUnitName, String tenantIdentifier) {
LOG.debugv("resolveConnectionProvider(persistenceUnitName={0}, tenantIdentifier={1})", persistenceUnitName,
tenantIdentifier);
// TODO when we switch to the non-legacy method, don't forget to update the definition of the default bean
// of type DataSourceTenantConnectionResolver (add the @PersistenceUnitExtension qualifier to that bean)
InjectableInstance<TenantConnectionResolver> instance = PersistenceUnitUtil
.legacySingleExtensionInstanceForPersistenceUnit(
TenantConnectionResolver.class, persistenceUnitName);
if (instance.isUnsatisfied()) {
throw new IllegalStateException(
String.format(
Locale.ROOT, "No instance of %1$s was found for persistence unit %2$s. "
+ "You need to create an implementation for this interface to allow resolving the current tenant connection.",
TenantConnectionResolver.class.getSimpleName(), persistenceUnitName));
}
TenantConnectionResolver resolver = instance.get();
ConnectionProvider cp = resolver.resolve(tenantIdentifier);
if (cp == null) {
throw new IllegalStateException("Method 'TenantConnectionResolver."
+ "resolve(String)' returned a null value. This violates the contract of the interface!");
}
return cp;
}
/**
* Retrieves the tenant resolver or fails if it is not available.
*
* @return Current tenant resolver.
*/
private static InstanceHandle<TenantResolver> tenantResolver(String persistenceUnitName) {
InjectableInstance<TenantResolver> instance = PersistenceUnitUtil
.legacySingleExtensionInstanceForPersistenceUnit(
TenantResolver.class, persistenceUnitName);
if (instance.isUnsatisfied()) {
throw new IllegalStateException(String.format(Locale.ROOT,
"No instance of %1$s was found for persistence unit %2$s. "View on GitHub (pinned to e1c734241f)
Solutions
- Make resolve() return a valid ConnectionProvider for the tenant or throw a descriptive exception when the tenant is unknown
- Add configuration for the missing tenant datasource/schema
- Validate the incoming tenant id against an allowlist before passing it to Hibernate
- Log the offending tenantIdentifier to spot mismatches
Example fix
// before
@Override
public ConnectionProvider resolve(String tenantId) {
return providers.get(tenantId); // null for unknown tenant
}
// after
@Override
public ConnectionProvider resolve(String tenantId) {
ConnectionProvider cp = providers.get(tenantId);
if (cp == null) {
throw new IllegalArgumentException("Unknown tenant: " + tenantId);
}
return cp;
} Defensive patterns
Strategy: validation
Validate before calling
Set<String> knownTenants = loadTenantConfig();
if (!knownTenants.contains(incomingTenantId)) {
throw new IllegalArgumentException("Unknown tenant: " + incomingTenantId);
} Type guard
Predicate<String> isKnownTenant = t -> t != null && tenantProviders.containsKey(t);
Try / catch
try {
em.find(E.class, id);
} catch (IllegalStateException e) {
if (e.getMessage().contains("resolve(String)")) { throw new UnknownTenantException(currentTenantId); }
throw e;
} Prevention
- Validate incoming tenant ids against configured tenants/datasources before DB access
- Never return null from resolve(); throw or fall back to a documented default
- Keep tenant ids case-consistent between headers and configuration keys
When it happens
Trigger: Multi-tenancy enabled, a TenantConnectionResolver bean is found, but resolve(tenantIdentifier) returns null — e.g., the tenant id is unknown to the resolver and the implementation returns null instead of throwing.
Common situations: Request carries a tenant id with no matching datasource/tenant configuration; schema-based resolver gets a tenant with no mapped schema; typo in tenant id vs quarkus.datasource."<name>" config keys; version changes in how tenant identifiers are resolved (case sensitivity).
Related errors
- Method 'TenantResolver.getDefaultTenantId()' returned a null
- No instance of %1$s was found for persistence unit %2$s. You
- No instance of %1$s was found for persistence unit %2$s. You
- No instance of %1$s was found for persistence unit %2$s. You
- Methods that are annotated with JPA Listener annotations sho
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/af6ed9f1b7036fc7.
Report an issue: GitHub.