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

  1. Resolve the Method from the target interface: Executor.class.getMethod("query", ...), not from the implementing class.
  2. Only intercept methods declared on Executor, ParameterHandler, ResultSetHandler, or StatementHandler.
  3. 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

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


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/e4fd41adff706153. Report an issue: GitHub.