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

  1. 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.
  2. 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.
  3. 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

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


AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14). Data as JSON: /api/errors/d1af914869c41080. Report an issue: GitHub.