alibaba/canal · error · IllegalArgumentException

No such method: '{}' @ {}

Error message

No such method: '{}' @ {}

What it means

Thrown by the private reflection helper invokeMethod() in DirectLogFetcher when objClazz.getMethod(name) raises NoSuchMethodException. The library uses reflection to reach into the mysql driver's undocumented classes (ConnectionImpl / its IO) during open(), so this signals the driver's internal method surface has changed or the wrong class was passed.

Source

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

            } catch (ClassNotFoundException e) {
                // com.mysql.jdbc.Connection not found.
            } catch (SQLException e) {
                logger.warn("Unwrap " + conn.getClass().getName() + " to " + connClazz.getName() + " failed: "
                            + e.getMessage(),
                    e);
            }

            return null;
        }
        return conn;
    }

    private static final Object invokeMethod(Object obj, Class<?> objClazz, String name) {
        try {
            Method method = objClazz.getMethod(name, (Class<?>[]) null);
            return method.invoke(obj, (Object[]) null);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("No such method: \'" + name + "\' @ " + objClazz.getName(), e);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Cannot invoke method: \'" + name + "\' @ " + objClazz.getName(), e);
        } catch (InvocationTargetException e) {
            throw new IllegalArgumentException("Invoke method failed: \'" + name + "\' @ " + objClazz.getName(),
                e.getTargetException());
        }
    }

    private static final Object getDeclaredField(Object obj, Class<?> objClazz, String name) {
        try {
            Field field = objClazz.getDeclaredField(name);
            field.setAccessible(true);
            return field.get(obj);
        } catch (NoSuchFieldException e) {
            throw new IllegalArgumentException("No such field: \'" + name + "\' @ " + objClazz.getName(), e);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Cannot get field: \'" + name + "\' @ " + objClazz.getName(), e);
        }

View on GitHub (pinned to 87be50e876)

Solutions

  1. Check the message for the exact class + method name, then compare against the actual mysql-connector-java version on the classpath.
  2. Pin mysql-connector-java to a 5.1.x release that still exposes com.mysql.jdbc.ConnectionImpl and its expected methods.
  3. If you must use driver 8.x, switch to a dbsync/connector build that targets the 8.x internal layout (com.mysql.cj.jdbc.JdbcConnection) instead of relying on this fork's reflection.
  4. Ensure no shading/relocation is stripping or renaming the driver classes fetched reflectively.

Example fix

// before - relies on driver internals
Class<?> connClazz = Class.forName("com.mysql.jdbc.ConnectionImpl");
Object connIo = getDeclaredField(unwrapConn, connClazz, "io");

// after - pin compatible driver in pom
<!-- mysql-connector-java 5.1.x exposes ConnectionImpl; avoid 8.x for this fork -->
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the driver class exposes the expected method before relying on it
Class<?> c = Class.forName("com.mysql.jdbc.ConnectionImpl");
boolean ok = false;
for (java.lang.reflect.Method m : c.getMethods()) {
    if (m.getName().equals("getIO") && m.getParameterCount() == 0) { ok = true; break; }
}
if (!ok) throw new IllegalStateException("driver missing expected ConnectionImpl method");

Try / catch

try {
    fetcher.open(conn, file, pos, serverId, false);
} catch (IllegalArgumentException e) { // wrapped NoSuchMethodException
    throw new IOException("mysql driver method surface mismatch - pin connector/j 5.1.x", e);
}

Prevention

When it happens

Trigger: invokeMethod(obj, objClazz, name) is called against a mysql driver class whose API no longer declares a no-arg method 'name' (or the class resolved is a different one than the driver build the library was written against).

Common situations: Upgrading mysql-connector-java (e.g. 5.1 -> 8.x) renames or removes internal connection methods; running against a driver fork or a shaded/relocated driver; passing a proxy/wrapper class instead of the real ConnectionImpl.

Related errors


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