hibernate/hibernate-orm · error · UnknownUnwrapTypeException

Cannot unwrap to requested type [{}]

Error message

Cannot unwrap to requested type [{}]

What it means

Thrown by AbstractMultiTenantConnectionProvider.unwrap(Class) when the requested unwrap type is neither the provider instance itself (or a supertype of its concrete class) nor ConnectionProvider. Hibernate's multi-tenant connection providers only expose these two unwrap targets; anything else raises UnknownUnwrapTypeException. This is the standard JPA-style 'unwrap' contract, so frameworks commonly hit it when probing for concrete implementation types.

Source

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

		return getAnyConnectionProvider().supportsAggressiveRelease();
	}

	@Override
	public boolean isUnwrappableAs(@Nonnull Class<?> unwrapType) {
		return unwrapType.isInstance( this )
			|| unwrapType.isAssignableFrom( ConnectionProvider.class );
	}

	@Override
	public <X> X unwrap(@Nonnull Class<X> unwrapType) {
		if ( unwrapType.isInstance( this ) ) {
			return unwrapType.cast( this );
		}
		else if ( unwrapType.isAssignableFrom( ConnectionProvider.class ) ) {
			return unwrapType.cast(  getAnyConnectionProvider() );
		}
		else {
			throw new UnknownUnwrapTypeException( unwrapType );
		}
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Unwrap to ConnectionProvider.class instead, then use getAnyConnectionProvider() or getConnectionProvider(tenantId) to reach the concrete per-tenant provider
  2. Unwrap to the concrete runtime class of the provider (or one of its supertypes that type.isInstance(provider) accepts)
  3. If you own the provider class, override unwrap() in your AbstractMultiTenantConnectionProvider subclass to support additional target types
  4. Get the DataSource another way (e.g. direct JNDI lookup) instead of unwrapping the connection provider

Example fix

// before
DataSource ds = multiTenantProvider.unwrap(DataSource.class); // UnknownUnwrapTypeException

// after
ConnectionProvider cp = multiTenantProvider.unwrap(ConnectionProvider.class);
DataSource ds = cp.unwrap(DataSource.class); // delegate to the underlying per-tenant provider
Defensive patterns

Strategy: type-guard

Validate before calling

// before unwrap: check the contract the base class enforces
if ( !type.isInstance(provider) && !ConnectionProvider.class.isAssignableFrom(type) ) {
    throw new IllegalArgumentException("Unsupported unwrap target: " + type);
}

Type guard

static boolean canUnwrap(MultiTenantConnectionProvider provider, Class<?> type) {
    return type.isInstance(provider) || ConnectionProvider.class.isAssignableFrom(type);
}

Try / catch

try {
    return provider.unwrap(type);
} catch (UnknownUnwrapTypeException e) {
    // fall back to reaching the concrete provider explicitly
    return type.cast(provider.getAnyConnectionProvider());
}

Prevention

When it happens

Trigger: Calling provider.unwrap(X.class) on an AbstractMultiTenantConnectionProvider subclass where X is not satisfied by type.isInstance(this) and X.isAssignableFrom(ConnectionProvider.class) is false - e.g. unwrap(DataSource.class), unwrap(DriverManagerConnectionProviderImpl.class) when the provider is DataSourceBasedMultiTenantConnectionProviderImpl, or unwrap to a pool-manager class (HikariDataSource, AgroalDataSource).

Common situations: Integration code (Spring, Quarkus, Micronaut, metrics/transaction managers) tries to unwrap the SessionFactory's connection provider to reach the underlying pool or DataSource. Custom MultiTenantConnectionProvider implementations that inherit the base unwrap behavior but are asked for tenant-specific types.

Related errors


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