alibaba/canal · error · IllegalArgumentException

mismatch class type

Error message

mismatch class type

What it means

TypeUtil.toObject(byte[], Class<T>) deserializes bytes into a typed Java object for NATIVE mode. It handles String, primitives, BigDecimal/BigInteger, java.sql.Date/Time/Timestamp, Date, Byte. Any other Class falls through to 'throw new IllegalArgumentException("mismatch class type")'. The class is simply not supported by this converter.

Source

Thrown at client-adapter/hbase/src/main/java/com/alibaba/otter/canal/client/adapter/hbase/support/TypeUtil.java:135

            res = bytes[0];
        } else if (BigDecimal.class == clazz) {
            res = Bytes.toBigDecimal(bytes);
        } else if (BigInteger.class == clazz) {
            res = Bytes.toLong(bytes);
        } else if (java.sql.Date.class == clazz) {
            long ts = Bytes.toLong(bytes);
            res = new java.sql.Date(ts);
        } else if (Time.class == clazz) {
            long ts = Bytes.toLong(bytes);
            res = new Time(ts);
        } else if (Timestamp.class == clazz) {
            long ts = Bytes.toLong(bytes);
            res = new Timestamp(ts);
        } else if (Date.class == clazz) {
            long ts = Bytes.toLong(bytes);
            res = new Date(ts);
        } else {
            throw new IllegalArgumentException("mismatch class type");
        }
        return (T) res;
    }

    @SuppressWarnings("unchecked")
    public static <T> T toObject(byte[] bytes, Type type) {
        if (bytes == null) {
            return null;
        }
        Object res = null;
        if (type == Type.STRING || type == Type.DEFAULT) {
            res = Bytes.toString(bytes);
        } else if (type == Type.INTEGER) {
            if (bytes.length == Bytes.SIZEOF_INT) {
                res = Bytes.toInt(bytes);
            }
        } else if (type == Type.LONG) {
            if (bytes.length == Bytes.SIZEOF_LONG) {

View on GitHub (pinned to 87be50e876)

Solutions

  1. Use one of the supported classes (String, Integer, Long, Short, Boolean, Float, Double, Byte, BigDecimal, BigInteger, java.sql.Date, Time, Timestamp, Date).
  2. If you need an unsupported type, deserialize to String/byte[] first then convert in your own code.
  3. For dates prefer java.util.Date or java.sql.Timestamp; avoid java.time types with this utility.
  4. Store the value as a String and parse on read if no native type fits.

Example fix

// before
LocalDate d = TypeUtil.toObject(bytes, LocalDate.class); // unsupported

// after
Timestamp ts = TypeUtil.toObject(bytes, Timestamp.class);
LocalDate d = ts.toLocalDateTime().toLocalDate();
Defensive patterns

Strategy: type-guard

Validate before calling

private static final Set<Class<?>> SUPPORTED = Set.of(
    String.class, Integer.class, int.class, Long.class, long.class,
    Short.class, short.class, Boolean.class, boolean.class,
    Float.class, float.class, Double.class, double.class,
    Byte.class, byte.class, BigDecimal.class, BigInteger.class,
    java.sql.Date.class, Time.class, Timestamp.class, Date.class);
if (!SUPPORTED.contains(clazz)) {
    throw new IllegalArgumentException("Unsupported class for TypeUtil.toObject: " + clazz);
}

Type guard

public static boolean isSupportedByTypeUtil(Class<?> clazz) {
    return clazz == String.class || clazz == Integer.class || clazz == int.class
        || clazz == Long.class || clazz == long.class || clazz == Short.class
        || clazz == short.class || clazz == Boolean.class || clazz == boolean.class
        || clazz == Float.class || clazz == float.class || clazz == Double.class
        || clazz == double.class || clazz == Byte.class || clazz == byte.class
        || clazz == BigDecimal.class || clazz == BigInteger.class
        || clazz == java.sql.Date.class || clazz == Time.class
        || clazz == Timestamp.class || clazz == Date.class;
}

Try / catch

try {
    T v = TypeUtil.toObject(bytes, clazz);
} catch (IllegalArgumentException e) {
    if ("mismatch class type".equals(e.getMessage())) {
        logger.error("Class " + clazz + " not supported; use String/Date/primitive wrapper");
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling TypeUtil.toObject(bytes, SomeOtherClass.class) where SomeOtherClass is not in the supported set (e.g. a custom POJO, enum, LocalDate, Calendar, java.util.Calendar, etc.).

Common situations: Configuring an HBase mapping to deserialize a column into an unsupported Java type; custom code reading HBase via TypeUtil with a non-primitive class.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/11702fdcd6af4e40. Report an issue: GitHub.