apache/shardingsphere · warning · SQLException

Unable to unwrap runtime database data source to `%s`.

Error message

Unable to unwrap runtime database data source to `%s`.

What it means

Thrown by the synthetic DataSource wrapper inside MCPJdbcDatabaseProfileLoader.DataSourceSupplier (a minimal delegating DataSource used to probe database metadata): unwrap(iface) only succeeds when the wrapper itself implements the requested interface, otherwise it throws SQLException with the target interface name. This follows the JDBC Wrapper contract strictly — the wrapper holds no reference to the real underlying DataSource to delegate unwrap to.

Source

Thrown at mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoader.java:157

            throw new SQLFeatureNotSupportedException();
        }
        
        @Override
        public int getLoginTimeout() throws SQLException {
            throw new SQLFeatureNotSupportedException();
        }
        
        @Override
        public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            throw new SQLFeatureNotSupportedException();
        }
        
        @Override
        public <T> T unwrap(final Class<T> iface) throws SQLException {
            if (iface.isInstance(this)) {
                return iface.cast(this);
            }
            throw new SQLException(String.format("Unable to unwrap runtime database data source to `%s`.", iface.getName()));
        }
        
        @Override
        public boolean isWrapperFor(final Class<?> iface) {
            return iface.isInstance(this);
        }
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Call isWrapperFor(targetClass) first and skip the vendor-specific path when it returns false.
  2. Use only JDBC-standard DataSource methods on this wrapper; it exists solely to supply connections for metadata profiling, not to expose vendor APIs.
  3. Access the real vendor DataSource from wherever it was originally constructed, not through this loader's wrapper.

Example fix

// before
MysqlDataSource mysql = dataSource.unwrap(MysqlDataSource.class);
// after
if (dataSource.isWrapperFor(MysqlDataSource.class)) {
    MysqlDataSource mysql = dataSource.unwrap(MysqlDataSource.class);
} else {
    // fall back to standard DataSource usage; vendor API not exposed by this wrapper
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!dataSource.isWrapperFor(PGDataSource.class)) { /* vendor-specific path unavailable; use standard DataSource API */ }

Type guard

boolean canUnwrap(DataSource ds, Class<?> iface) { return ds.isWrapperFor(iface); }

Try / catch

try {
    T vendor = dataSource.unwrap(iface);
} catch (final SQLException ex) {
    // message names the unsupported interface; degrade to standard JDBC usage
}

Prevention

When it happens

Trigger: Calling unwrap(X.class) on this profile-loading DataSource for any interface it does not itself implement (e.g. unwrap(PoolDataSource.class), unwrap(MysqlDataSource.class)). isWrapperFor(iface) returns true only for iface.isInstance(this), so it predicts exactly what unwrap will accept.

Common situations: Library code (connection pools, drivers, monitoring agents) calling unwrap to reach vendor-specific datasource APIs, or casting-based access paths that assume the original DataSource is reachable behind any DataSource instance.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/35509863bb0d2347. Report an issue: GitHub.