alibaba/canal · critical · IOException

Unable to load com.mysql.jdbc.ConnectionImpl

Error message

Unable to load com.mysql.jdbc.ConnectionImpl

What it means

Thrown in DirectLogFetcher.open()'s catch(ClassNotFoundException) when Class.forName("com.mysql.jdbc.ConnectionImpl") fails - the legacy driver class is not on the classpath. This is the canonical signal that the deployed mysql driver does not contain the old com.mysql.jdbc package.

Source

Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/DirectLogFetcher.java:196

            // 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;
        } catch (ClassNotFoundException e) {
            close(); /* Do cleanup */
            throw new IOException("Unable to load com.mysql.jdbc.ConnectionImpl", e);
        }
    }

    /**
     * Put a byte in the buffer.
     * 
     * @param b the byte to put in the buffer
     */
    protected final void putByte(byte b) {
        ensureCapacity(position + 1);

        buffer[position++] = b;
    }

    /**
     * Put 16-bit integer in the buffer.
     * 
     * @param i16 the integer to put in the buffer

View on GitHub (pinned to 87be50e876)

Solutions

  1. Add mysql-connector-java 5.1.x to the classpath (it still ships com.mysql.jdbc.ConnectionImpl).
  2. If you must use driver 8.x, switch to a dbsync/connector revision that loads com.mysql.cj.jdbc.JdbcConnection instead.
  3. Verify with 'jar tf <driver>.jar | grep ConnectionImpl' whether the class is actually present.
  4. Resolve classpath conflicts so only one driver version is present and the legacy class is loadable.

Example fix

// before - driver 8.x on classpath, legacy class absent
fetcher.open(conn, file, pos, serverId); // -> Unable to load com.mysql.jdbc.ConnectionImpl

// after - pin a driver that still has the class
<!-- pom.xml -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.49</version>
</dependency>
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast if the legacy driver class is absent
try { Class.forName("com.mysql.jdbc.ConnectionImpl"); }
catch (ClassNotFoundException e) {
    throw new IllegalStateException("com.mysql.jdbc.ConnectionImpl missing - add mysql-connector-java 5.1.x", e);
}

Try / catch

try { fetcher.open(conn, file, pos, serverId, false); }
catch (IOException e) {
    if (e.getMessage().contains("Unable to load com.mysql.jdbc.ConnectionImpl"))
        throw new IOException("driver 8.x on classpath - pin connector/j 5.1.x or use a cj-compatible build", e);
    throw e;
}

Prevention

When it happens

Trigger: open() runs Class.forName("com.mysql.jdbc.ConnectionImpl") and the JVM cannot resolve the class, so the catch block re-throws it as IOException("Unable to load com.mysql.jdbc.ConnectionImpl", e).

Common situations: mysql-connector-java 8.0+ on the classpath, where the legacy com.mysql.jdbc.ConnectionImpl was removed (the com.mysql.cj.jdbc package replaces it); driver jar excluded from the build; an incompatible driver fork; classpath/shading stripped the class.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/6c4126ee947567ea. Report an issue: GitHub.