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

  1. Call isWrapperFor(iface) before unwrap() and skip the vendor-specific path when it returns false
  2. Use standard JDBC interfaces (java.sql.Connection, javax.sql.DataSource) instead of vendor classes where possible
  3. Construct the pool with config.setDataSource(realVendorDataSource) so the vendor type is actually underneath and unwrap succeeds
  4. 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

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


AI-assisted analysis of brettwooldridge/HikariCP@a4d93f4f85 (2026-08-14). Data as JSON: /api/errors/c1fb3f5a2f909ffe. Report an issue: GitHub.