brettwooldridge/HikariCP · error · SQLException
Wrapped DataSource is not an instance of ${iface}
Error message
Wrapped DataSource is not an instance of ${iface} What it means
HikariDataSource.unwrap(iface) only succeeds when the underlying (unwrapped) DataSource is an instance of the requested interface, or the delegate itself can unwrap it. HikariCP wraps a user-supplied DataSource, so it can only forward unwrap calls to what it actually wraps; otherwise it throws SQLException.
Source
Thrown at src/main/java/com/zaxxer/hikari/HikariDataSource.java:201
public <T> T unwrap(Class<T> iface) throws SQLException
{
if (iface.isInstance(this)) {
return (T) this;
}
var p = pool;
if (p != null) {
final var unwrappedDataSource = p.getUnwrappedDataSource();
if (iface.isInstance(unwrappedDataSource)) {
return (T) unwrappedDataSource;
}
if (unwrappedDataSource != null) {
return unwrappedDataSource.unwrap(iface);
}
}
throw new SQLException("Wrapped DataSource is not an instance of " + iface);
}
/** {@inheritDoc} */
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException
{
if (iface.isInstance(this)) {
return true;
}
var p = pool;
if (p != null) {
final var unwrappedDataSource = p.getUnwrappedDataSource();
if (iface.isInstance(unwrappedDataSource)) {
return true;
}
if (unwrappedDataSource != null) {View on GitHub (pinned to a4d93f4f85)
Solutions
- Call isWrapperFor(iface) before unwrap() and skip the vendor-specific path when it returns false
- Use standard JDBC interfaces (java.sql.Connection, javax.sql.DataSource) instead of vendor classes where possible
- Construct the pool with config.setDataSource(realVendorDataSource) so the vendor type is actually underneath and unwrap succeeds
- Pass the vendor-specific handle out-of-band (keep your own reference) instead of unwrapping
Example fix
// before
OracleDataSource ods = hikariDs.unwrap(OracleDataSource.class); // throws
// after
if (hikariDs.isWrapperFor(OracleDataSource.class)) {
OracleDataSource ods = hikariDs.unwrap(OracleDataSource.class);
} else {
// fall back to standard JDBC or keep a direct vendor reference
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!hikariDs.isWrapperFor(VendorDataSource.class)) {
// use standard JDBC path or a kept vendor reference
} Type guard
boolean canUnwrapDs(DataSource ds, Class<?> iface) {
try { return ds.isWrapperFor(iface); }
catch (SQLException e) { return false; }
} Try / catch
try { v = ds.unwrap(iface); }
catch (SQLException e) {
if (e.getMessage().contains("not an instance of")) { /* fallback to standard API */ }
else throw e;
} Prevention
- Always call isWrapperFor before unwrap
- Configure pool with the vendor DataSource instance if you need vendor unwrap
- Avoid vendor-specific unwrap on jdbcUrl-built pools
When it happens
Trigger: Calling ds.unwrap(OracleDataSource.class) (or any driver-specific class) when the pool was built from a DriverDataSource (jdbcUrl-based) which has no such type; unwrapping to a class the real driver DataSource does not implement; calling unwrap before the pool exists (pool == null).
Common situations: Migrating from native driver DataSources to HikariCP while keeping vendor-specific unwrap calls (e.g. oracle.ucp, MysqlDataSource); unwrap() called on a HikariDataSource created with jdbcUrl instead of dataSource instance.
Related errors
- Wrapped connection is not an instance of ${iface}
- Wrapped DatabaseMetaData is not an instance of {}
- Wrapped ResultSet is not an instance of {}
- Wrapped statement is not an instance of {}
- Failed to load class ${className}
AI-assisted analysis of brettwooldridge/HikariCP@a4d93f4f85 (2026-08-14).
Data as JSON: /api/errors/c1fb3f5a2f909ffe.
Report an issue: GitHub.