mybatis/mybatis-3 · error · ReflectionException

Illegal overloaded getter method with ambiguous type for pro

Error message

Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results.

What it means

AmbiguousMethodInvoker replaces a normal MethodInvoker when Reflector finds two getters resolving to the same property with incompatible types (e.g. getX() and isX() returning different types, or overloaded getX() with unrelated return types). Any later read of that property throws this ReflectionException instead of silently picking one — an explicit fail-fast because the JavaBeans spec forbids such pairs.

Source

Thrown at src/main/java/org/apache/ibatis/reflection/invoker/AmbiguousMethodInvoker.java:33

 */
package org.apache.ibatis.reflection.invoker;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.ibatis.reflection.ReflectionException;

public class AmbiguousMethodInvoker extends MethodInvoker {
  private final String exceptionMessage;

  public AmbiguousMethodInvoker(Method method, String exceptionMessage) {
    super(method);
    this.exceptionMessage = exceptionMessage;
  }

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    throw new ReflectionException(exceptionMessage);
  }
}

View on GitHub (pinned to 008069adb1)

Solutions

  1. Rename or delete one of the conflicting accessors so a single getter serves the property.
  2. If isX() and getX() must coexist, make their types consistent or annotate the property mapping to a different, unambiguous property.
  3. Wrap the offending class in a clean DTO for MyBatis mapping instead of mapping the generated class directly.

Example fix

// before
public Status getStatus() { ... }
public boolean isStatus() { ... }  // ambiguous with getStatus()
// after
public Status getStatus() { ... }
public boolean hasStatus() { ... }
Defensive patterns

Strategy: validation

Validate before calling

// detect ambiguous getters before MyBatis touches the class
Map<String, Set<Class<?>>> byProperty = new HashMap<>();
for (Method m : Dto.class.getMethods()) {
  String p = propertyNameOf(m); // getX -> x, isX -> x
  if (p != null) byProperty.computeIfAbsent(p, k -> new HashSet<>()).add(m.getReturnType());
}
boolean ambiguous = byProperty.values().stream().anyMatch(s -> s.size() > 1);

Prevention

When it happens

Trigger: A class used as parameter or result type declaring both T getX() and boolean isX() (or two getX() overloads with unrelated returns); MyBatis registers the collision and throws the moment the property is accessed.

Common situations: Generated code (Thrift/Protobuf/ANTLR visitors) with is/set overloads; refactoring a boolean to an enum/object while keeping the old is-getter; third-party DTOs pulled in as resultType.

Related errors


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