mybatis/mybatis-3 · error · BindingException
Error getting mapper instance. Cause
Error message
Error getting mapper instance. Cause: {cause} What it means
MapperProxyFactory.newInstance() failed while creating the JDK dynamic proxy for the mapper interface. The cause is chained in the message ('Cause: ...'); typical causes are failures in instantiating the proxy, errors thrown from mapper interface default methods during construction of the invoker cache, or classloader issues in managed environments.
Solutions
- Read the chained 'Cause:' exception first - it names the real failure (IllegalAccessException, etc.)
- For JPMS, open/export the mapper's package to org.apache.ibatis or add the needed --add-opens JVM flags
- Ensure one classloader loads both mybatis and the mapper interfaces (avoid duplicated jars across webapp and container libs)
Example fix
# example JPMS fix java --add-opens com.example.mappers/com.example.mappers=org.apache.ibatis ...
Defensive patterns
Strategy: try-catch
Try / catch
try {
FooMapper m = session.getMapper(FooMapper.class);
} catch (BindingException e) {
log.error("Mapper proxy creation failed: {}", e.getCause().getMessage(), e.getCause());
throw e; // classloader/module problems are not recoverable at runtime
} Prevention
- Keep mybatis and mapper interfaces in the same classloader (no duplicated jars across webapp/container)
- For JPMS deployments, add --add-opens for mapper packages
- Always log the chained cause; the root reason is never the wrapper message
When it happens
Trigger: Any reflective failure while building the MapperProxy: e.g. inaccessible default methods under strict module boundaries (Java 16+ strong encapsulation), a SecurityManager denying proxy creation, or classloader mismatch (mapper interface visible to a different loader than MyBatis).
Common situations: App servers with parent-last classloading; OSGi containers; JPMS deployments where org.apache.ibatis cannot access the mapper interface; finalizing environments where reflection is restricted.
Related errors
- Cannot find class
- Error creating lazy proxy. Cause: " + e
- Invalid bound statement (not found)
- Mapper method ' ' attempted to return null from a method…
- Mapper method ' ' has an unsupported return type
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/365a4fe2ccf1e93e.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/apache/ibatis/binding/MapperRegistry.java:52
public class MapperRegistry {
private final Configuration config;
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new ConcurrentHashMap<>();
public MapperRegistry(Configuration config) {
this.config = config;
}
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
public <T> boolean hasMapper(Class<T> type) {
return knownMappers.containsKey(type);
}
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
knownMappers.put(type, new MapperProxyFactory<>(type));
// It's important that the type is added before the parser is run
// otherwise the binding may automatically be attempted by the
// mapper parser. If the type is already known, it won't try.View on GitHub (pinned to 008069adb1)