mybatis/mybatis-3 · error · IllegalArgumentException
Method '{}' is not supported as a plugin target.
Error message
Method '{}' is not supported as a plugin target. What it means
Invocation's constructor rejects any method whose declaring class is not one of the four plugin target interfaces: Executor, ParameterHandler, ResultSetHandler, StatementHandler. MyBatis plugins can only intercept these interfaces, and Invocation enforces that contract at construction.
Source
Thrown at src/main/java/org/apache/ibatis/plugin/Invocation.java:41
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
/**
* @author Clinton Begin
*/
public class Invocation {
private static final List<Class<?>> targetClasses = Arrays.asList(Executor.class, ParameterHandler.class,
ResultSetHandler.class, StatementHandler.class);
private final Object target;
private final Method method;
private final Object[] args;
public Invocation(Object target, Method method, Object[] args) {
if (!targetClasses.contains(method.getDeclaringClass())) {
throw new IllegalArgumentException("Method '" + method + "' is not supported as a plugin target.");
}
this.target = target;
this.method = method;
this.args = args;
}
public Object getTarget() {
return target;
}
public Method getMethod() {
return method;
}
public Object[] getArgs() {
return args;
}
View on GitHub (pinned to 008069adb1)
Solutions
- Resolve the Method from the target interface: Executor.class.getMethod("query", ...), not from the implementing class.
- Only intercept methods declared on Executor, ParameterHandler, ResultSetHandler, or StatementHandler.
- If you need to intercept something else, use a different mechanism (e.g. decorator around the SqlSessionFactory), not the plugin Invocation API.
Example fix
// before
Method m = target.getClass().getMethod("query", MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class);
new Invocation(target, m, args);
// after
Method m = Executor.class.getMethod("query", MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class);
new Invocation(target, m, args); Defensive patterns
Strategy: validation
Validate before calling
private static final List<Class<?>> TARGETS = Arrays.asList(Executor.class, ParameterHandler.class, ResultSetHandler.class, StatementHandler.class);
if (!TARGETS.contains(method.getDeclaringClass())) throw new IllegalArgumentException("not a plugin target"); Type guard
boolean isPluginTarget(Method m) {
return m != null && TARGETS.contains(m.getDeclaringClass());
} Prevention
- Always resolve intercepted Methods from the four target interfaces, never from implementation classes.
- Treat the plugin API as closed: anything outside Executor/ParameterHandler/ResultSetHandler/StatementHandler needs a decorator, not a plugin.
When it happens
Trigger: new Invocation(target, method, args) where method.getDeclaringClass() is outside the allowed list — e.g. a method from a concrete class, Object, or another interface; typically hit by custom code wrapping the plugin API or reflecting a method resolved from an implementation class instead of the interface.
Common situations: Custom interceptors or frameworks building Invocation manually; obtaining the Method via target.getClass().getMethod(...) instead of Executor.class.getMethod(...); JDK default methods whose declaring class differs from the target interface.
Related errors
- No @Intercepts annotation was found in interceptor {}
- Could not find method on {} named {}. Cause: {}
- Error creating instance. Cause: {cause}
- Error in result map '{resultMapId}'. Failed to find a constr
- Failed to create a new Configuration instance.
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/e4fd41adff706153.
Report an issue: GitHub.