mybatis/mybatis-3 · error · PluginException
Could not find method on {} named {}. Cause: {}
Error message
Could not find method on {} named {}. Cause: {} What it means
Plugin.getSignatureMap() resolves each @Signature with Class.getMethod(name, args) and throws PluginException when lookup fails. The signature must name a real public method with exact parameter types on the given target interface.
Source
Thrown at src/main/java/org/apache/ibatis/plugin/Plugin.java:81
}
}
private static Map<Class<?>, Set<Method>> getSignatureMap(Interceptor interceptor) {
Intercepts interceptsAnnotation = interceptor.getClass().getAnnotation(Intercepts.class);
// issue #251
if (interceptsAnnotation == null) {
throw new PluginException(
"No @Intercepts annotation was found in interceptor " + interceptor.getClass().getName());
}
Signature[] sigs = interceptsAnnotation.value();
Map<Class<?>, Set<Method>> signatureMap = new HashMap<>();
for (Signature sig : sigs) {
Set<Method> methods = signatureMap.computeIfAbsent(sig.type(), k -> new HashSet<>());
try {
Method method = sig.type().getMethod(sig.method(), sig.args());
methods.add(method);
} catch (NoSuchMethodException e) {
throw new PluginException("Could not find method on " + sig.type() + " named " + sig.method() + ". Cause: " + e,
e);
}
}
return signatureMap;
}
private static Class<?>[] getAllInterfaces(Class<?> type, Map<Class<?>, Set<Method>> signatureMap) {
Set<Class<?>> interfaces = new HashSet<>();
while (type != null) {
for (Class<?> c : type.getInterfaces()) {
if (signatureMap.containsKey(c)) {
interfaces.add(c);
}
}
type = type.getSuperclass();
}
return interfaces.toArray(new Class<?>[0]);
}View on GitHub (pinned to 008069adb1)
Solutions
- Cross-check the method name and full parameter list against the exact MyBatis version's interface source (Executor, ParameterHandler, ResultSetHandler, StatementHandler).
- After a MyBatis upgrade, review every @Signature for changed parameter lists (e.g. six-arg Executor.query).
- Use parameterized args to catch drift at compile time instead of hard-coded Class literals.
Example fix
// before
@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}))
// after
@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})) Defensive patterns
Strategy: validation
Validate before calling
// startup self-check of signatures
for (Signature s : interceptor.getClass().getAnnotation(Intercepts.class).value()) {
s.type().getMethod(s.method(), s.args()); // throws NoSuchMethodException early, with a clear message
} Prevention
- After any MyBatis version bump, re-verify every @Signature against the new interface javadoc.
- Write one unit test per interceptor that boots a Configuration with the plugin registered, so signature errors fail the build, not production.
When it happens
Trigger: @Signature(type = StatementHandler.class, method = "prepared", args = {Connection.class}) — wrong name, wrong arg count, wrong arg types/order, or a method that only exists on a different target interface.
Common situations: Upgrading MyBatis across versions where target-interface method signatures changed (classic: Executor.query gained BoundSql/CacheKey overloads); typos in method names; assuming a method exists on StatementHandler when it is on ResultSetHandler.
Related errors
- Method '{}' is not supported as a plugin target.
- No @Intercepts annotation was found in interceptor {}
- Not allowed to update a null cache key instance.
- Unknown execution method for: {name}
- Mapper method '{name}' attempted to return null from a metho
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/ee4d26924de24e62.
Report an issue: GitHub.