mybatis/mybatis-3 · error · IllegalArgumentException
name + " already contains key " + key
Error message
name + " already contains key " + key
What it means
Configuration.StrictMap.put() rejects duplicate full keys: every mapped statement, result map, parameter map, and sql fragment is stored in a StrictMap keyed by its fully-qualified id (namespace + '.' + id). Registering a second object with the same full name throws IllegalArgumentException with the map name, the key, and an optional producer-supplied conflict detail. This is MyBatis' guard against ambiguous statement ids.
Source
Thrown at src/main/java/org/apache/ibatis/session/Configuration.java:1158
* function arguments are 1st is saved value and 2nd is target value.
*
* @param conflictMessageProducer
* A function for producing a conflict error message
*
* @return a conflict error message
*
* @since 3.5.0
*/
public StrictMap<V> conflictMessageProducer(BiFunction<V, V, String> conflictMessageProducer) {
this.conflictMessageProducer = conflictMessageProducer;
return this;
}
@Override
@SuppressWarnings("unchecked")
public V put(String key, V value) {
if (containsKey(key)) {
throw new IllegalArgumentException(name + " already contains key " + key
+ (conflictMessageProducer == null ? "" : conflictMessageProducer.apply(super.get(key), value)));
}
if (key.contains(".")) {
final String shortKey = getShortName(key);
if (super.get(shortKey) == null) {
super.put(shortKey, value);
} else {
super.put(shortKey, (V) AMBIGUITY_INSTANCE);
}
}
return super.put(key, value);
}
@Override
public boolean containsKey(Object key) {
if (key == null) {
return false;
}View on GitHub (pinned to 008069adb1)
Solutions
- Search all mapper XML and annotation mappers for the duplicated id shown in the message and rename one of them.
- Ensure each file has a unique namespace (conventionally the fully-qualified mapper interface name).
- Remove duplicate <mapper> registrations pointing at the same resource (check mybatis-config.xml and Spring's mapperLocations/@MapperScan).
- If using annotations, do not duplicate an annotated method id that also exists in an XML bound to the same namespace.
Example fix
// before <mapper namespace="com.acme.UserMapper"> <select id="findById">...</select> <select id="findById">...</select> </mapper> // after <mapper namespace="com.acme.UserMapper"> <select id="findById">...</select> <select id="findByName">...</select> </mapper>
Defensive patterns
Strategy: validation
Validate before calling
// Fail fast on duplicates before adding: StrictMap already throws on put, // so validate your XML at startup by building the Configuration once in CI.
Try / catch
try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(config); }
catch (IllegalArgumentException e) { /* message shows map name + duplicate key; rename or deregister */ throw e; } Prevention
- One unique namespace per mapper file, matching the interface FQCN.
- Do not register the same resource twice (check mybatis-config <mappers> and Spring mapperLocations).
- Avoid annotating a method that already has an XML statement with the same id.
When it happens
Trigger: Two <select>/<insert>/<update>/<delete> with the same id in one mapper XML namespace; the same statement id in both an XML file and an annotated mapper interface method within one namespace; registering the same mapper resource twice (mybatis-config <mapper> entries duplicated, or Spring component scan + @MapperScan overlap); same resultMap id defined in two files with the same namespace.
Common situations: Merging mapper files during refactoring; copy-paste of a statement without changing its id; legacy XML mapper plus new annotation-based mapper colliding after @MapperScan is added; namespace attribute copy-pasted so two files share a namespace.
Related errors
- 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}
- Error creating instance. Cause: {cause}
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/6e07a3704b8a17d5.
Report an issue: GitHub.