baomidou/mybatis-plus · error · IllegalArgumentException

Failed to serialize object of type: {}

Error message

Failed to serialize object of type: {}

What it means

SerializationUtils.serialize(object) writes the object to an ObjectOutputStream and converts any IOException into IllegalArgumentException('Failed to serialize object of type: <class>'). In practice the almost-universal cause is NotSerializableException (a subclass of IOException): some object in the graph does not implement java.io.Serializable.

Source

Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/SerializationUtils.java:64

        return (T) deserialize(objectData);
    }

    /**
     * Serialize the given object to a byte array.
     *
     * @param object the object to serialize
     * @return an array of bytes representing the object in a portable fashion
     */
    public static byte[] serialize(Object object) {
        if (object == null) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(object);
            oos.flush();
        } catch (IOException ex) {
            throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
        }
        return baos.toByteArray();
    }

    /**
     * Deserialize the byte array into an object.
     *
     * @param bytes a serialized object
     * @return the result of deserializing the bytes
     */
    public static Object deserialize(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
            return ois.readObject();
        } catch (IOException ex) {
            throw new IllegalArgumentException("Failed to deserialize object", ex);

View on GitHub (pinned to bf67d90747)

Solutions

  1. Make every class in the object graph implement Serializable (including nested types and superclasses).
  2. Mark non-serializable/transient-volatile references as transient and reconstruct them in readResolve/writeReplace if needed.
  3. If a field cannot be serialized, exclude it from the cached form (DTO projection) or switch the cache to a non-serializing store.
  4. Check the wrapped NotSerializableException in the cause chain — it names the exact offending class.

Example fix

// before
public class User implements Serializable {
    private Connection conn; // NotSerializableException inside IOException
}

// after
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private transient Connection conn;
}
Defensive patterns

Strategy: validation

Validate before calling

if (object != null && !(object instanceof java.io.Serializable)
        && !isPrimitivelySerializable(object)) {
    throw new IllegalArgumentException("object graph must be Serializable: " + object.getClass());
}

Type guard

static boolean isSerializableDeep(Class<?> c, Set<Class<?>> seen) {
    if (c == null || c.isPrimitive() || Serializable.class.isAssignableFrom(c)
            || c == String.class || Number.class.isAssignableFrom(c)) return true;
    if (!seen.add(c)) return true;
    for (Field f : c.getDeclaredFields()) {
        if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) continue;
        if (!isSerializableDeep(f.getType(), seen)) return false;
    }
    return true;
}

Try / catch

try {
    byte[] bytes = SerializationUtils.serialize(obj);
} catch (IllegalArgumentException e) {
    Throwable cause = e.getCause(); // NotSerializableException names the offending class
    throw new IllegalStateException("Non-serializable element: " + cause, e);
}

Prevention

When it happens

Trigger: Passing an object graph containing a non-Serializable element (a field holding a Connection, InputStream, lambda capturing one, Thread, or a POJO without implements Serializable). mybatis-plus uses this helper for cache puts (second-level cache serialization) and similar plumbing.

Common situations: Enabling a serialized second-level cache on mappers whose entities embed non-serializable fields (e.g. java.time fields in old setups, custom types, open streams); caching entities with lazy-loading proxy objects that hold session internals.

Related errors


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