baomidou/mybatis-plus · error · IllegalArgumentException
Type argument cannot be null
Error message
Type argument cannot be null
What it means
EnumCache.metadata(enumClassType) looks up (and lazily builds) the cached EnumMetadata for an enum class used by mybatis-plus's enum type-handling (IEnum or @EnumValue based enums). A null class argument throws IllegalArgumentException('Type argument cannot be null'). This is a hard precondition: the cache is keyed by Class, so null is meaningless.
Source
Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/EnumCache.java:54
* @author hubin
* @since 2026-07-01
*/
final class EnumCache {
private static final String ENUM_VALUE_PROPERTY = "value";
private static final String NO_ENUM_VALUE_FIELD = "";
private static final Object[] EMPTY_ARGS = new Object[0];
private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();
private static final ConcurrentHashMap<Class<?>, EnumMetadata> CACHE = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Class<?>, String> ENUM_VALUE_FIELD_CACHE = new ConcurrentHashMap<>();
private EnumCache() {
// utility class
}
static EnumMetadata metadata(Class<?> enumClassType) {
if (enumClassType == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
return CACHE.computeIfAbsent(enumClassType, EnumCache::createMetadata);
}
static Optional<String> findEnumValueFieldName(Class<?> clazz) {
if (clazz == null || !clazz.isEnum()) {
return Optional.empty();
}
String fieldName = ENUM_VALUE_FIELD_CACHE.computeIfAbsent(clazz, EnumCache::findEnumValueFieldNameOrEmpty);
return NO_ENUM_VALUE_FIELD.equals(fieldName) ? Optional.empty() : Optional.of(fieldName);
}
static boolean isMpEnums(Class<?> clazz) {
return clazz != null && clazz.isEnum() && (IEnum.class.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());
}
private static EnumMetadata createMetadata(Class<?> enumClassType) {
if (!enumClassType.isEnum()) {View on GitHub (pinned to bf67d90747)
Solutions
- Trace which code path resolved the enum class and returned null — typically the property type resolution in the type handler registry for the mapped statement.
- Ensure the entity field is a concrete enum type (not a type variable or Object) and the resultMap/parameterMap declares javaType if generics erase it.
- Register the enum explicitly (default-enum-type-handler / typeHandler on the field) so mybatis-plus never has to infer a null type.
Example fix
// before
public MyHandler(Class<E> enumType) {
this.meta = EnumCacheHelper.lookup(enumType); // enumType null -> IAE
}
// after
public MyHandler(Class<E> enumType) {
Objects.requireNonNull(enumType, "enumType must be resolved from the mapped property");
this.meta = EnumCacheHelper.lookup(enumType);
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> enumType = resolveEnumType(); // may return null Objects.requireNonNull(enumType, "enum type must be resolvable from the mapped property"); EnumCache.metadata(enumType); // package-private internally; guard at your boundary
Type guard
static boolean isResolvableEnum(Class<?> c) {
return c != null && c.isEnum();
} Try / catch
try {
EnumCache.metadata(enumType);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Enum property type unresolved for field " + field, e);
} Prevention
- Null-check every reflectively resolved type before handing it to framework caches.
- Prefer explicit typeHandler/javaType registration so enum types are never inferred and cannot be null.
When it happens
Trigger: The package-private metadata(Class) is invoked with null, which in practice happens when a caller resolved the entity's enum property type and got null (unresolvable generic type, missing field on the meta object) and passed it on unchecked. It can surface during MybatisEnumTypeHandler construction or enum value lookup for a column whose Java property type could not be determined.
Common situations: Mapping configuration where the JavaType for an enum column ends up null (resultMap missing javaType, generic erasure on a custom wrapper); building a type handler manually with a null class argument.
Related errors
- Type argument must be an enum: {}
- Type argument cannot be null
- Failed invoking constructor for handler %s
- Unable to find a usable constructor for %s
- Type argument cannot be null
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/d1af914869c41080.
Report an issue: GitHub.