{"record":{"id":"d1af914869c41080","repo":"baomidou/mybatis-plus","slug":"type-argument-cannot-be-null-d1af91","errorCode":null,"errorMessage":"Type argument cannot be null","messagePattern":"Type argument cannot be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/EnumCache.java","lineNumber":54,"sourceCode":" * @author hubin\n * @since 2026-07-01\n */\nfinal class EnumCache {\n\n    private static final String ENUM_VALUE_PROPERTY = \"value\";\n    private static final String NO_ENUM_VALUE_FIELD = \"\";\n    private static final Object[] EMPTY_ARGS = new Object[0];\n    private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();\n    private static final ConcurrentHashMap<Class<?>, EnumMetadata> CACHE = new ConcurrentHashMap<>();\n    private static final ConcurrentHashMap<Class<?>, String> ENUM_VALUE_FIELD_CACHE = new ConcurrentHashMap<>();\n\n    private EnumCache() {\n        // utility class\n    }\n\n    static EnumMetadata metadata(Class<?> enumClassType) {\n        if (enumClassType == null) {\n            throw new IllegalArgumentException(\"Type argument cannot be null\");\n        }\n        return CACHE.computeIfAbsent(enumClassType, EnumCache::createMetadata);\n    }\n\n    static Optional<String> findEnumValueFieldName(Class<?> clazz) {\n        if (clazz == null || !clazz.isEnum()) {\n            return Optional.empty();\n        }\n        String fieldName = ENUM_VALUE_FIELD_CACHE.computeIfAbsent(clazz, EnumCache::findEnumValueFieldNameOrEmpty);\n        return NO_ENUM_VALUE_FIELD.equals(fieldName) ? Optional.empty() : Optional.of(fieldName);\n    }\n\n    static boolean isMpEnums(Class<?> clazz) {\n        return clazz != null && clazz.isEnum() && (IEnum.class.isAssignableFrom(clazz) || findEnumValueFieldName(clazz).isPresent());\n    }\n\n    private static EnumMetadata createMetadata(Class<?> enumClassType) {\n        if (!enumClassType.isEnum()) {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/EnumCache.java#L36-L72","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npublic MyHandler(Class<E> enumType) {\n    this.meta = EnumCacheHelper.lookup(enumType); // enumType null -> IAE\n}\n\n// after\npublic MyHandler(Class<E> enumType) {\n    Objects.requireNonNull(enumType, \"enumType must be resolved from the mapped property\");\n    this.meta = EnumCacheHelper.lookup(enumType);\n}","handlingStrategy":"validation","validationCode":"Class<?> enumType = resolveEnumType(); // may return null\nObjects.requireNonNull(enumType, \"enum type must be resolvable from the mapped property\");\nEnumCache.metadata(enumType); // package-private internally; guard at your boundary","typeGuard":"static boolean isResolvableEnum(Class<?> c) {\n    return c != null && c.isEnum();\n}","tryCatchPattern":"try {\n    EnumCache.metadata(enumType);\n} catch (IllegalArgumentException e) {\n    throw new IllegalStateException(\"Enum property type unresolved for field \" + field, e);\n}","preventionTips":["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."],"tags":["enum","type-handler","argument-validation"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}