alibaba/canal · error · IOException
Unable to unwrap {} to com.mysql.jdbc.ConnectionImpl
Error message
Unable to unwrap {} to com.mysql.jdbc.ConnectionImpl What it means
Thrown in DirectLogFetcher.open() when unwrapConnection() returns null - i.e. the supplied java.sql.Connection could not be unwrapped (directly, via reflection, or via Wrapper.unwrap) to com.mysql.jdbc.ConnectionImpl. The library needs the raw driver connection to read its private IO streams, so an unwrappable connection is fatal.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/DirectLogFetcher.java:175
/**
* Connect MySQL master to fetch binlog.
*/
public void open(Connection conn, String fileName, final long filePosition, final int serverId) throws IOException {
open(conn, fileName, filePosition, serverId, false);
}
/**
* Connect MySQL master to fetch binlog.
*/
public void open(Connection conn, String fileName, long filePosition, final int serverId, boolean nonBlocking)
throws IOException {
try {
this.conn = conn;
Class<?> connClazz = Class.forName("com.mysql.jdbc.ConnectionImpl");
Object unwrapConn = unwrapConnection(conn, connClazz);
if (unwrapConn == null) {
throw new IOException("Unable to unwrap " + conn.getClass().getName()
+ " to com.mysql.jdbc.ConnectionImpl");
}
// Get underlying IO streams for network communications.
Object connIo = getDeclaredField(unwrapConn, connClazz, "io");
if (connIo == null) {
throw new IOException("Get null field:" + conn.getClass().getName() + "#io");
}
mysqlOutput = (OutputStream) getDeclaredField(connIo, connIo.getClass(), "mysqlOutput");
mysqlInput = (InputStream) getDeclaredField(connIo, connIo.getClass(), "mysqlInput");
if (filePosition == 0) filePosition = BIN_LOG_HEADER_SIZE;
sendBinlogDump(fileName, filePosition, serverId, nonBlocking);
position = 0;
} catch (IOException e) {
close(); /* Do cleanup */
logger.error("Error on COM_BINLOG_DUMP: file = " + fileName + ", position = " + filePosition);
throw e;
View on GitHub (pinned to 87be50e876)
Solutions
- Inspect conn.getClass().getName() in the message and confirm it is a real mysql driver connection (or can unwrap to one).
- Downgrade to mysql-connector-java 5.1.x which still ships com.mysql.jdbc.ConnectionImpl.
- If staying on driver 8.x, switch to a dbsync build that targets com.mysql.cj.jdbc.JdbcConnection, or fetch the binlog over the network protocol instead of via driver reflection.
- Configure the pool to expose the underlying connection (e.g. HikariConfig.setAllowPoolSuspension / unwrap the delegate) before passing it to open().
Example fix
// before - pooled/proxy connection cannot be unwrapped
fetcher.open(dataSource.getConnection(), file, pos, serverId);
// after - unwrap to the real driver connection first
Connection raw = dataSource.getConnection();
if (raw.isWrapperFor(com.mysql.jdbc.Connection.class)) {
raw = raw.unwrap(com.mysql.jdbc.Connection.class);
}
fetcher.open(raw, file, pos, serverId); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the connection can unwrap to the legacy driver class before open
Connection c = dataSource.getConnection();
if (c.isWrapperFor(com.mysql.jdbc.Connection.class)) {
c = c.unwrap(com.mysql.jdbc.Connection.class);
} else {
throw new IOException("connection is not a com.mysql.jdbc.Connection - use connector/j 5.1.x");
} Try / catch
try { fetcher.open(conn, file, pos, serverId, false); }
catch (IOException e) {
if (e.getMessage().contains("Unable to unwrap"))
throw new IOException("need a raw connector/j 5.1.x connection", e);
throw e;
} Prevention
- Use mysql-connector-java 5.1.x which exposes com.mysql.jdbc.ConnectionImpl.
- Unwrap pooled connections to the physical driver connection before passing to open().
- Do not pass XA/proxy logical connections that hide the underlying driver object.
When it happens
Trigger: open(conn, ...) is called with a Connection that is not, and cannot be unwrapped to, com.mysql.jdbc.ConnectionImpl: a pooling-proxy wrapper, a non-mysql driver, or mysql-connector-java 8.x where ConnectionImpl has been removed in favor of com.mysql.cj.jdbc.JdbcConnection.
Common situations: Using HikariCP/DBCP/c3p0 with a delegate that hides the real connection; running against mysql-connector-java 8.x (the legacy com.mysql.jdbc.* package is gone); passing a logical connection from an XA pool; a test/stub connection.
Related errors
- Get null field:{}#io
- No such method: '{}' @ {}
- No such field: '{}' @ {}
- Unable to load com.mysql.jdbc.ConnectionImpl
- Invoke method failed: '{}' @ {}
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/29dcc615b8edbce5.
Report an issue: GitHub.