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

  1. Always declare javaType when registering: <typeHandler handler="...EnumOrdinalTypeHandler" javaType="com.example.MyEnum"/>
  2. Ensure the mapper property/parameter has a resolvable java type (add javaType= to #{...} or the resultMap)
  3. 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

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


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/90b2828bb6b0fb6d. Report an issue: GitHub.