alibaba/canal · error · IllegalArgumentException

Cannot invoke method: '{}' @ {}

Error message

Cannot invoke method: '{}' @ {}

What it means

Thrown by invokeMethod() when Method.invoke raises IllegalAccessException. The helper does NOT call setAccessible(true) on methods (unlike getDeclaredField), so any non-public method, a Java module that denies access, or an active SecurityManager will trip this.

Source

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

            } 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. Add the driver module to --add-opens (e.g. --add-opens java.base/java.lang=ALL-UNNAMED) or open the mysql driver package to dbsync.
  2. Remove/disable the SecurityManager if it is not required for the deployment.
  3. Pin to a mysql-connector-java version whose internal methods are public and match the reflection targets.
  4. If you control the build, patch invokeMethod to call method.setAccessible(true) before invoke.

Example fix

// before
Method method = objClazz.getMethod(name, (Class<?>[]) null);
return method.invoke(obj, (Object[]) null);

// after - force accessibility like getDeclaredField does
Method method = objClazz.getMethod(name, (Class<?>[]) null);
method.setAccessible(true);
return method.invoke(obj, (Object[]) null);
Defensive patterns

Strategy: validation

Validate before calling

// Check the JVM will allow reflective invocation before opening
java.lang.reflect.Method m = connClazz.getMethod("someMethod");
try { m.setAccessible(true); }
catch (SecurityException se) { throw new IllegalStateException("JVM blocks reflective access - add --add-opens", se); }

Try / catch

try { fetcher.open(conn, file, pos, serverId, false); }
catch (IllegalArgumentException e) {
    if (e.getCause() instanceof IllegalAccessException)
        throw new IOException("module/security blocks driver reflection", e);
    throw e;
}

Prevention

When it happens

Trigger: invokeMethod resolves a method via getMethod but invoking it is forbidden: the method is package-private/protected, the JVM runs under a SecurityManager, or a JPMS module boundary blocks reflective invocation.

Common situations: Running dbsync under a restrictive container/agent with a SecurityManager, on Java 9+ where the mysql driver is not 'open' to dbsync, or against a driver version that changed a method's access modifier.

Related errors


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