baomidou/mybatis-plus · error · IllegalStateException
Duplicate key {}
Error message
Duplicate key {} What it means
ReflectionKit.excludeOverrideSuperField builds a name-to-Field map of a subclass's declared fields using Collectors.toMap with a merge function that throws IllegalStateException('Duplicate key <field>') on key collision. In Java, one class cannot declare two fields with the same name, so a duplicate here means the input Field[] contains the same field twice — i.e. a class is present multiple times in the type hierarchy traversal (often with interface/default-method or bridge situations in mybatis-plus versions of that era).
Source
Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ReflectionKit.java:168
/* 过滤 transient关键字修饰的属性 */
.filter(f -> !Modifier.isTransient(f.getModifiers()))
.collect(Collectors.toList());
});
}
/**
* <p>
* 排序重置父类属性
* </p>
*
* @param fields 子类属性
* @param superFieldList 父类属性
*/
public static Map<String, Field> excludeOverrideSuperField(Field[] fields, List<Field> superFieldList) {
// 子类属性
Map<String, Field> fieldMap = Stream.of(fields).collect(toMap(Field::getName, identity(),
(u, v) -> {
throw new IllegalStateException("Duplicate key " + u);
}, LinkedHashMap::new));
superFieldList.stream().filter(field -> !fieldMap.containsKey(field.getName()))
.forEach(f -> fieldMap.put(f.getName(), f));
return fieldMap;
}
/**
* 判断是否为基本类型或基本包装类型
*
* @param clazz class
* @return 是否基本类型或基本包装类型
*/
@Deprecated
public static boolean isPrimitiveOrWrapper(Class<?> clazz) {
Assert.notNull(clazz, "Class must not be null");
return (clazz.isPrimitive() || PRIMITIVE_WRAPPER_TYPE_MAP.containsKey(clazz));
}
View on GitHub (pinned to bf67d90747)
Solutions
- Upgrade mybatis-plus to the latest patch release — duplicate-field traversal bugs in excludeOverrideSuperField callers were fixed in subsequent versions.
- If calling the API directly, deduplicate the Field[] by name (and declaring class) before passing it in.
- Inspect the entity hierarchy: remove redundant re-declaration of a field in both a subclass and an interface/default context that triggers duplicate discovery.
Example fix
// before
Map<String, Field> map = ReflectionKit.excludeOverrideSuperField(dupFields, superFields);
// after: dedupe by name first
Map<String, Field> unique = Arrays.stream(dupFields)
.collect(Collectors.toMap(Field::getName, Function.identity(), (a, b) -> a, LinkedHashMap::new));
Map<String, Field> map = ReflectionKit.excludeOverrideSuperField(unique.values().toArray(new Field[0]), superFields); Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>();
for (Field f : fields) {
if (!seen.add(f.getName() + "@" + f.getDeclaringClass().getName())) {
throw new IllegalStateException("duplicate field in input: " + f);
}
}
Map<String, Field> m = ReflectionKit.excludeOverrideSuperField(fields, superFields); Type guard
static boolean hasNoDuplicateNames(Field[] fields) {
Set<String> names = new HashSet<>();
for (Field f : fields) if (!names.add(f.getName())) return false;
return true;
} Try / catch
try {
Map<String, Field> m = ReflectionKit.excludeOverrideSuperField(fields, superFields);
} catch (IllegalStateException e) {
throw new IllegalStateException("duplicate field discovered in hierarchy — upgrade mybatis-plus", e);
} Prevention
- Deduplicate field arrays by name before reflective map building.
- Keep mybatis-plus current; hierarchy-traversal duplicates were fixed in later 3.4.x/3.5.x patches.
When it happens
Trigger: Calling ReflectionKit.excludeOverrideSuperField(fields, superFields) (or mybatis-plus entity metadata init that calls it) where the fields array contains two Field objects with the same name — e.g. getDeclaredFields() of a class that javac duplicated fields for (visibility-bridge generics with covariant overrides), or a user supplying a hand-built Field[] containing duplicates.
Common situations: Entity classes with generic hierarchies where reflection sees duplicate bridge-backed fields; bugs in older mybatis-plus versions (3.4.x era) resolved in later releases; user code copying this helper and feeding it unchecked field lists.
Related errors
- Failed to create a new Configuration instance.
- Unable to find a usable constructor for %s
- Unable to retrieve the mapperInterface and sqlSession proper
- There is neither 'privateLookupIn(Class, Lookup)' nor 'Looku
- Cannot find class: {}
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/0b0b9531f6a7bf41.
Report an issue: GitHub.