alibaba/canal · error · IllegalArgumentException
No such field: '{}' @ {}
Error message
No such field: '{}' @ {} What it means
Thrown by the private helper getDeclaredField() when objClazz.getDeclaredField(name) raises NoSuchFieldException. DirectLogFetcher reflects on undocumented mysql driver fields (io, mysqlOutput, mysqlInput on the connection/IO objects), so this means the expected field name is gone from the resolved driver class.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/DirectLogFetcher.java:138
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);
}
}
/**
* Connect MySQL master to fetch binlog.
*/
public void open(Connection conn, String fileName, final int serverId) throws IOException {
open(conn, fileName, BIN_LOG_HEADER_SIZE, serverId, false);
}
/**
* Connect MySQL master to fetch binlog.
*/
public void open(Connection conn, String fileName, final int serverId, boolean nonBlocking) throws IOException {
open(conn, fileName, BIN_LOG_HEADER_SIZE, serverId, nonBlocking);
}
View on GitHub (pinned to 87be50e876)
Solutions
- Read the message for the class + field name and check whether that field still exists in your mysql-connector-java jar (javap on the class).
- Pin mysql-connector-java to the 5.1.x line that this fork of dbsync was written against.
- Eliminate multiple driver versions on the classpath so the reflected class is the one expected.
- If migrating to driver 8.x is required, use a dbsync/connector revision updated for the cj-package internal field layout.
Example fix
// before - field name hardcoded against old driver
mysqlOutput = (OutputStream) getDeclaredField(connIo, connIo.getClass(), "mysqlOutput");
// after - verify field exists, else fail fast with guidance
Field f;
try { f = connIo.getClass().getDeclaredField("mysqlOutput"); }
catch (NoSuchFieldException nsf) {
throw new IOException("mysql driver layout changed: missing mysqlOutput on "
+ connIo.getClass().getName() + " - pin connector/j 5.1.x", nsf);
} Defensive patterns
Strategy: validation
Validate before calling
// Confirm the reflected field still exists on the resolved driver class
java.lang.reflect.Field f;
try { f = Class.forName("com.mysql.jdbc.ConnectionImpl").getDeclaredField("io"); }
catch (NoSuchFieldException | ClassNotFoundException nf) {
throw new IllegalStateException("driver layout incompatible - pin connector/j 5.1.x", nf);
} Try / catch
try { fetcher.open(conn, file, pos, serverId, false); }
catch (IllegalArgumentException e) {
if (e.getCause() instanceof NoSuchFieldException)
throw new IOException("mysql driver field layout changed", e);
throw e;
} Prevention
- Keep the driver version aligned with the dbsync fork's expectations (5.1.x).
- Resolve classpath conflicts so only one driver version is present.
- Run a build-time or startup smoke test that reflects on the expected fields.
When it happens
Trigger: getDeclaredField(obj, objClazz, name) is asked for a field the resolved mysql driver class no longer declares (e.g. 'io' on ConnectionImpl, 'mysqlOutput'/'mysqlInput' on MysqlIO). Typical during open() while wiring the raw IO streams.
Common situations: mysql-connector-java upgrade (5.1 -> 8.x) renamed/removed internal fields; a driver fork or shaded artifact; resolving a different class than expected due to classpath conflicts.
Related errors
- No such method: '{}' @ {}
- Invoke method failed: '{}' @ {}
- Unable to unwrap {} to com.mysql.jdbc.ConnectionImpl
- Get null field:{}#io
- Unable to load com.mysql.jdbc.ConnectionImpl
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/dc67190b424a9ed9.
Report an issue: GitHub.