apache/shardingsphere · error · SQLFeatureNotSupportedException

`%s` cannot be unwrapped as `%s`

Error message

`%s` cannot be unwrapped as `%s`

What it means

SQLFeatureNotSupportedException from WrapperAdapter.unwrap(Class<T>) when the requested iface is not an instance of the wrapper object (isWrapperFor returns false). ShardingSphere's JDBC wrappers only unwrap to types they actually implement — the ShardingSphere class hierarchy, not the underlying vendor Connection/Statement classes.

Source

Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/adapter/WrapperAdapter.java:42

import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.sql.Wrapper;

/**
 * Adapter for {@code java.sql.Wrapper}.
 */
@Getter
public abstract class WrapperAdapter implements Wrapper {
    
    private final MethodInvocationRecorder<Statement> methodInvocationRecorder = new MethodInvocationRecorder<>();
    
    @SuppressWarnings("unchecked")
    @Override
    public final <T> T unwrap(final Class<T> iface) throws SQLException {
        if (isWrapperFor(iface)) {
            return (T) this;
        }
        throw new SQLFeatureNotSupportedException(String.format("`%s` cannot be unwrapped as `%s`", getClass().getName(), iface.getName()));
    }
    
    @Override
    public final boolean isWrapperFor(final Class<?> iface) {
        return iface.isInstance(this);
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Use unwrap with interfaces the proxy implements (java.sql.Connection, Statement, etc.) — these succeed.
  2. Fetch the vendor connection through ShardingSphere's own escape hatch (e.g. getRawConnection()/driver-specific API or execute on the physical datasource) instead of unwrap.
  3. Configure the framework/ORM to disable the vendor-specific feature that triggers the unwrap call.
  4. Isolate vendor-specific operations on a separate, non-ShardingSphere datasource.

Example fix

// before
MySQLConnection mysql = conn.unwrap(MySQLConnection.class); // throws
// after
// run vendor-specific work on the underlying pool directly
try (Connection raw = hikariDataSource.getConnection()) {
    MySQLConnection mysql = raw.unwrap(MySQLConnection.class);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!conn.isWrapperFor(MySQLConnection.class)) { /* vendor API unavailable via proxy */ }

Type guard

boolean canUnwrapVendor(Connection c, Class<?> iface) { return c.isWrapperFor(iface); }

Try / catch

try { MySQLConnection mc = conn.unwrap(MySQLConnection.class); } catch (SQLFeatureNotSupportedException ex) { fallbackToGenericPath(); }

Prevention

When it happens

Trigger: Calling unwrap() on a ShardingSphere Connection/Statement/ResultSet with a class the proxy does not implement — most commonly MySQLConnection.class, PGConnection.class, or another driver-specific interface expected by ORM or framework code.

Common situations: Libraries trying to access vendor-specific APIs through the proxy (e.g. MySQL 'useLocalSessionState' tweaks, COPY for Postgres); Hibernate/JOOQ feature detection via unwrap; code assuming the proxy forwards unwrap to the real connection.

Related errors


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