mybatis/mybatis-3 · error · IllegalArgumentException
key + " is ambiguous in " + name + " (try using the full nam
Error message
key + " is ambiguous in " + name + " (try using the full name including the namespace, or rename one of the entries)
What it means
StrictMap stores a short-name index (the segment after the last dot) next to every full key. When two different full keys share the same short name, the short slot is overwritten with the sentinel AMBIGUITY_INSTANCE; a later get() by that short name throws IllegalArgumentException saying the key is ambiguous and suggesting the full name including namespace. This only affects lookups that omit the namespace.
Source
Thrown at src/main/java/org/apache/ibatis/session/Configuration.java:1188
}
@Override
public boolean containsKey(Object key) {
if (key == null) {
return false;
}
return super.get(key) != null;
}
@Override
public V get(Object key) {
V value = super.get(key);
if (value == null) {
throw new IllegalArgumentException(name + " does not contain value for " + key);
}
if (AMBIGUITY_INSTANCE == value) {
throw new IllegalArgumentException(key + " is ambiguous in " + name
+ " (try using the full name including the namespace, or rename one of the entries)");
}
return value;
}
private String getShortName(String key) {
final String[] keyParts = key.split("\\.");
return keyParts[keyParts.length - 1];
}
}
}
View on GitHub (pinned to 008069adb1)
Solutions
- Always reference statements and maps by their fully-qualified name: namespace + '.' + id.
- If you truly need short names, rename one of the colliding ids so short names are unique.
- Audit dynamically-built statement strings to ensure the namespace prefix is retained.
Example fix
// before
sqlSession.selectList("findById", 1);
// after
sqlSession.selectList("com.acme.UserMapper.findById", 1); Defensive patterns
Strategy: validation
Validate before calling
String full = UserMapper.class.getName() + ".findById"; // never look up by short name; assert the full name resolves assert factory.getConfiguration().hasStatement(full);
Try / catch
try { session.selectList("findById"); }
catch (IllegalArgumentException e) { /* 'is ambiguous' -> switch to full name including namespace */ throw e; } Prevention
- Always use namespace-qualified statement names.
- Ban short-name lookups in code review.
- Give ids descriptive names so cross-mapper collisions are obvious (findUserById vs findById).
When it happens
Trigger: Two statements named findById in different namespaces (e.g. UserMapper.findById and OrderMapper.findById) and a lookup with just "findById"; two resultMaps with the same short id across namespaces referenced without namespace; statement string built dynamically and accidentally stripped of the namespace part.
Common situations: Generic DAO code calling statements by short id; copy-paste ids across mappers (findById everywhere); older code that relied on short names before mappers grew; string manipulation (split on '.') that drops the namespace.
Related errors
- name + " does not contain value for " + key
- Invalid bound statement (not found): {mapperInterface}.{meth
- Type {type} is not known to the MapperRegistry.
- Error resolving JdbcType. Cause: {cause}
- Error resolving ResultSetType. Cause: {cause}
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/d77f99ec33aecd05.
Report an issue: GitHub.