apache/shardingsphere · error · SQLFeatureNotSupportedException
`%s` cannot be unwrapped as `%s`
Error message
`%s` cannot be unwrapped as `%s`
What it means
RawResultSetMetaData implements the standard JDBC Wrapper contract minimally: unwrap(iface) succeeds only when iface.isInstance(this) — i.e. only RawResultSetMetaData itself or its supertypes. Requesting any other interface (JDBC4ResultSetMetaData, driver-specific metadata, etc.) throws SQLFeatureNotSupportedException with the class names formatted into the message. Raw metadata simply does not wrap any richer implementation.
Source
Thrown at infra/executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/execute/result/query/impl/raw/metadata/RawResultSetMetaData.java:208
return String.class.getName();
default:
return Object.class.getName();
}
}
private RawQueryResultColumnMetaData getColumnMetaData(final int column) throws SQLException {
if (column < 1 || column > columns.size()) {
throw new SQLException(String.format("Column index out of range: %s", column));
}
return columns.get(column - 1);
}
@Override
public <T> T unwrap(final Class<T> iface) throws SQLException {
if (isWrapperFor(iface)) {
return iface.cast(this);
}
throw new SQLFeatureNotSupportedException(String.format("`%s` cannot be unwrapped as `%s`", getClass().getName(), iface.getName()));
}
@Override
public boolean isWrapperFor(final Class<?> iface) {
return iface.isInstance(this);
}
}
View on GitHub (pinned to e952770a21)
Solutions
- Call isWrapperFor(iface) first and skip the vendor-specific path when it returns false.
- Do vendor-specific metadata access on a connection that bypasses ShardingSphere, or accept the generic metadata interface only.
- Replace unwrap-based feature detection with SQL-level capability checks (DatabaseMetaData) that ShardingSphere forwards.
Example fix
// before
PgResultSetMetaData md = resultSet.getMetaData().unwrap(PgResultSetMetaData.class);
// after
ResultSetMetaData md = resultSet.getMetaData();
if (md.isWrapperFor(PgResultSetMetaData.class)) {
// vendor path on a direct driver connection only
} else {
// generic path: md.getColumnName(i), md.getColumnType(i), ...
} Defensive patterns
Strategy: type-guard
Type guard
if (metaData.isWrapperFor(PgResultSetMetaData.class)) { ... } // only then unwrap Try / catch
try { return metaData.unwrap(target); } catch (SQLFeatureNotSupportedException e) { /* fall back to generic ResultSetMetaData APIs */ } Prevention
- Call isWrapperFor before unwrap — standard Wrapper-contract hygiene.
- Keep vendor-specific metadata access on direct driver connections.
When it happens
Trigger: Calling resultSet.getMetaData().unwrap(org.postgresql.jdbc.PgResultSetMetaData.class) or unwrap(com.mysql.cj.jdbc.result.ResultSetMetaData.class) through ShardingSphere; generic framework code that tries unwrap(X) before falling back, where X is never the raw metadata class.
Common situations: Code migrated from a direct driver connection where unwrap of the driver metadata type worked; Spring/JDBC helper libraries probing for vendor-specific metadata to read vendor columns; tests asserting vendor metadata behavior through the ShardingSphere layer.
Related errors
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/ffcf0d7462744399.
Report an issue: GitHub.