{"record":{"id":"5b4e9d9463c35f5a","repo":"apache/shardingsphere","slug":"s-cannot-be-unwrapped-as-s-5b4e9d","errorCode":null,"errorMessage":"`%s` cannot be unwrapped as `%s`","messagePattern":"`(.+?)` cannot be unwrapped as `(.+?)`","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/adapter/WrapperAdapter.java","lineNumber":42,"sourceCode":"import java.sql.SQLFeatureNotSupportedException;\nimport java.sql.Statement;\nimport java.sql.Wrapper;\n\n/**\n * Adapter for {@code java.sql.Wrapper}.\n */\n@Getter\npublic abstract class WrapperAdapter implements Wrapper {\n    \n    private final MethodInvocationRecorder<Statement> methodInvocationRecorder = new MethodInvocationRecorder<>();\n    \n    @SuppressWarnings(\"unchecked\")\n    @Override\n    public final <T> T unwrap(final Class<T> iface) throws SQLException {\n        if (isWrapperFor(iface)) {\n            return (T) this;\n        }\n        throw new SQLFeatureNotSupportedException(String.format(\"`%s` cannot be unwrapped as `%s`\", getClass().getName(), iface.getName()));\n    }\n    \n    @Override\n    public final boolean isWrapperFor(final Class<?> iface) {\n        return iface.isInstance(this);\n    }\n}\n","sourceCodeStart":24,"sourceCodeEnd":50,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/adapter/WrapperAdapter.java#L24-L50","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use unwrap with interfaces the proxy implements (java.sql.Connection, Statement, etc.) — these succeed.","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.","Configure the framework/ORM to disable the vendor-specific feature that triggers the unwrap call.","Isolate vendor-specific operations on a separate, non-ShardingSphere datasource."],"exampleFix":"// before\nMySQLConnection mysql = conn.unwrap(MySQLConnection.class); // throws\n// after\n// run vendor-specific work on the underlying pool directly\ntry (Connection raw = hikariDataSource.getConnection()) {\n    MySQLConnection mysql = raw.unwrap(MySQLConnection.class);\n}","handlingStrategy":"type-guard","validationCode":"if (!conn.isWrapperFor(MySQLConnection.class)) { /* vendor API unavailable via proxy */ }","typeGuard":"boolean canUnwrapVendor(Connection c, Class<?> iface) { return c.isWrapperFor(iface); }","tryCatchPattern":"try { MySQLConnection mc = conn.unwrap(MySQLConnection.class); } catch (SQLFeatureNotSupportedException ex) { fallbackToGenericPath(); }","preventionTips":["Always call isWrapperFor before unwrap","Use a separate physical datasource for vendor-specific operations","Do not assume proxies forward unwrap to the real connection"],"tags":["jdbc","unwrap","wrapper","vendor-api"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}