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
- Call isWrapperFor(targetClass) first and skip the vendor-specific path when it returns false.
- Use only JDBC-standard DataSource methods on this wrapper; it exists solely to supply connections for metadata profiling, not to expose vendor APIs.
- 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
- Always pair unwrap with a prior isWrapperFor check
- Never assume vendor DataSource APIs are reachable through framework-supplied wrappers
- Fetch vendor handles at construction time, not through intermediaries
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
- `%s` cannot be unwrapped as `%s`
- `%s` cannot be unwrapped as `%s`
- Query did not return a result set.
- Unsupported BLR version: %s
- Expected blr_begin
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/35509863bb0d2347.
Report an issue: GitHub.