baomidou/mybatis-plus · error · IllegalArgumentException
%s already contains value for %s
Error message
%s already contains value for %s
What it means
Thrown by MybatisConfiguration.StrictMap.put when a duplicate key is registered in a strict map (mapper statements, result maps, sql fragments, parameter maps). MyBatis-Plus copies MyBatis's StrictMap semantics: each fully-qualified id must be unique, so re-registering an id is treated as a configuration defect rather than silently overwriting. The extra detail comes from an optional conflictMessageProducer that can show both conflicting values.
Source
Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisConfiguration.java:454
/**
* Assign a function for producing a conflict error message when contains value with the same key.
* <p>
* 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 value for " + key
+ (conflictMessageProducer == null ? StringPool.EMPTY : conflictMessageProducer.apply(super.get(key), value)));
}
if (useGeneratedShortKey) {
if (key.contains(StringPool.DOT)) {
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) {View on GitHub (pinned to bf67d90747)
Solutions
- Search all mapper XML namespaces and annotated mapper interfaces for the duplicated statement id shown in the message and rename one of them.
- If the id exists both as an annotation (@Select etc.) and in XML for the same mapper method, remove one of the two definitions.
- Check for the same XML file being loaded twice (duplicate <mapper resource=...> entries in mybatis-config.xml, or the same jar included twice in the build).
- If intentional overriding is required, register the overriding mapper in a different namespace instead of reusing the same id.
Example fix
<!-- before: two files both declare id selectById under namespace com.example.UserMapper --> <mapper namespace="com.example.UserMapper"> <select id="selectById">...</select> </mapper> <!-- after: give the second statement a distinct id/namespace --> <mapper namespace="com.example.UserMapperXml"> <select id="selectByIdLegacy">...</select> </mapper>
Defensive patterns
Strategy: validation
Validate before calling
// before building the SqlSessionFactory, assert no duplicate statement ids across mappers
Set<String> ids = new HashSet<>();
for (MapperMethod-ish m : allMapperMethods) { /* illustrative */ }
// practical check: after factory build, walk mapped statements
org.apache.ibatis.session.Configuration cfg = factory.getConfiguration();
Set<String> seen = new HashSet<>();
for (Object ms : new java.util.ArrayList<>(cfg.getMappedStatements())) {
if (ms instanceof org.apache.ibatis.mapping.MappedStatement) {
String id = ((org.apache.ibatis.mapping.MappedStatement) ms).getId();
if (!seen.add(id)) throw new IllegalStateException("Duplicate statement id: " + id);
}
} Try / catch
catch (IllegalArgumentException e) when message starts with the StrictMap name + " already contains value for" — extract the key from the message and report the conflicting mapper files; fail startup, do not retry.
Prevention
- One statement definition per id: keep annotations and XML mutually exclusive for the same method.
- Derive XML namespaces from the mapper interface FQCN by convention.
- Add a startup integration test that builds the SqlSessionFactory to catch duplicates before deploy.
When it happens
Trigger: Two XML mapper files or annotation methods defining the same statement id (e.g. 'com.example.UserMapper.selectById' in both an XML file and a @Select annotated method), or the same mapper XML loaded twice via different <mapper> entries; also registering two result maps or sql fragments with the same namespace-qualified id.
Common situations: Copying a mapper XML and forgetting to rename the namespace; mixing annotation-based statements with an XML file that has the same id; classpath duplication where the same mapper XML is packaged twice; switching a project to mybatis-plus while old MyBatis mapper XML files remain on the classpath.
Related errors
- %s does not contain value for %s
- %s is ambiguous in %s (try using the full name including the
- Should be specified either value() or name() attribute in th
- Cannot use both value() and name() attribute in the @CacheNa
- Detected conflicting annotations '%s' and '%s' on '%s'.
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/2a069f03138cb37b.
Report an issue: GitHub.