baomidou/mybatis-plus · error · IllegalStateException

Failed to deserialize object type

Error message

Failed to deserialize object type

What it means

The ClassNotFoundException branch of SerializationUtils.deserialize: the byte stream names a class that is not on the current classpath, rethrown as IllegalStateException('Failed to deserialize object type'). The data is intact but the code needed to materialize it is missing or moved.

Source

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

        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);
        } catch (ClassNotFoundException ex) {
            throw new IllegalStateException("Failed to deserialize object type", ex);
        }
    }
}

View on GitHub (pinned to bf67d90747)

Solutions

  1. Restore or re-add the missing class (the exception's cause names the exact class).
  2. Keep serialized class names stable: avoid renaming/moving entity classes that appear in serialized blobs, or migrate the data.
  3. Clear/flush serialized caches after refactors so stale entries are regenerated.
  4. For cross-service caches, serialize a neutral format (JSON/protobuf) instead of Java serialization.

Example fix

// before: entity moved from com.acme.old.User to com.acme.user.User; old blobs unreadable
// after: keep a compatibility alias or migrate data
package com.acme.old;
@Deprecated
public class User extends com.acme.user.User implements java.io.Serializable {
    private static final long serialVersionUID = <same as before>;
}
Defensive patterns

Strategy: fallback

Validate before calling

try {
    Class.forName(classNameFromStreamHeaderIfKnown, true, getClass().getClassLoader());
} catch (ClassNotFoundException e) {
    // data references a class missing here: migrate or evict before deserialize
}

Try / catch

try {
    return SerializationUtils.deserialize(bytes);
} catch (IllegalStateException e) { // ClassNotFoundException branch
    log.warn("serialized class missing on this node; evicting entry", e);
    cache.remove(key);
    return recompute(key);
}

Prevention

When it happens

Trigger: Deserializing bytes written when class X existed, in a JVM/process where X (or its package after a rename/refactor/shade) is absent. Also cross-application cache sharing where one app writes entities the reader does not have; mybatis-plus serialized cache read after an entity class was renamed or its package restructured.

Common situations: Refactoring/renaming entity classes while old serialized cache/blob entries persist; rolling deployments where new nodes lack a class old nodes wrote; shaded jars changing package names; shared distributed caches between differently-built services.

Related errors


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