mybatis/mybatis-3 · error · IllegalArgumentException
Type argument cannot be null
Error message
Type argument cannot be null
What it means
EnumOrdinalTypeHandler caches the enum constants at construction and requires the enum Class to do so. Passing a null Class to the constructor throws this IllegalArgumentException immediately — the handler refuses to operate without knowing the enum type.
Source
Thrown at src/main/java/org/apache/ibatis/type/EnumOrdinalTypeHandler.java:33
*/
package org.apache.ibatis.type;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author Clinton Begin
*/
public class EnumOrdinalTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
private final Class<E> type;
private final E[] enums;
public EnumOrdinalTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
this.enums = type.getEnumConstants();
if (this.enums == null) {
throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.ordinal());
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
int ordinal = rs.getInt(columnName);
if (ordinal == 0 && rs.wasNull()) {
return null;View on GitHub (pinned to 008069adb1)
Solutions
- Always declare javaType when registering: <typeHandler handler="...EnumOrdinalTypeHandler" javaType="com.example.MyEnum"/>
- Ensure the mapper property/parameter has a resolvable java type (add javaType= to #{...} or the resultMap)
- If constructing programmatically, never pass null — load the enum class first
Example fix
// before <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/> // after <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.example.Status"/>
Defensive patterns
Strategy: validation
Validate before calling
if (enumClass == null) throw new IllegalArgumentException("enumClass required for EnumOrdinalTypeHandler");
return new EnumOrdinalTypeHandler<>(enumClass); Type guard
static <E extends Enum<E>> EnumOrdinalTypeHandler<E> safeOrdinalHandler(Class<E> type) {
return type == null ? null : new EnumOrdinalTypeHandler<>(type);
} Try / catch
try { new EnumOrdinalTypeHandler<>(type); } catch (IllegalArgumentException e) { // null or non-enum type: fix registration } Prevention
- Always pair enum handler registrations with an explicit javaType
- Static-check configuration at startup: enumerate <typeHandler> entries and assert javaType is set for enum handlers
When it happens
Trigger: new EnumOrdinalTypeHandler<>(null); or registering the handler in XML/Configuration without a javaType so TypeHandlerRegistry instantiates it with a null type argument; default enum handling when the java type of a property could not be resolved.
Common situations: Declaring <typeHandler handler="...EnumOrdinalTypeHandler"/> with no javaType attribute; a mapper property whose javaType is left unresolved (e.g. generic erased fields) so MyBatis falls back to a null-typed enum handler.
Related errors
- Type argument cannot be null
- Type {typeHandlerType} is not a valid TypeHandler because it
- {} does not represent an enum type.
- Invalid bound statement (not found): {mapperInterface}.{meth
- Type {type} is not known to the MapperRegistry.
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/90b2828bb6b0fb6d.
Report an issue: GitHub.