apache/dubbo · error · IllegalArgumentException

[Serialization Security] Serialized class {className} has no

Error message

[Serialization Security] Serialized class {className} has not implement Serializable interface. Current mode is strict check, will disallow to deserialize it by default. 

What it means

During deserialization class loading, Dubbo detected a class that does not implement java.io.Serializable. With checkSerializable enabled (the strict default), Dubbo refuses to deserialize it to protect against untrusted class instantiation. The message is only thrown when serializeSecurityManager's checkSerializable flag is true.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/utils/DefaultSerializeClassChecker.java:119

    /**
     * Try load class
     *
     * @param className class name
     * @throws IllegalArgumentException if class is blocked
     */
    public Class<?> loadClass(ClassLoader classLoader, String className) throws ClassNotFoundException {
        Class<?> aClass = loadClass0(classLoader, className);
        if (!aClass.isPrimitive() && !Serializable.class.isAssignableFrom(aClass)) {
            String msg = "[Serialization Security] Serialized class " + className
                    + " has not implement Serializable interface. "
                    + "Current mode is strict check, will disallow to deserialize it by default. ";
            if (serializeSecurityManager.getWarnedClasses().add(className)) {
                logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg);
            }

            if (checkSerializable) {
                throw new IllegalArgumentException(msg);
            }
        }

        return aClass;
    }

    private Class<?> loadClass0(ClassLoader classLoader, String className) throws ClassNotFoundException {
        if (checkStatus == SerializeCheckStatus.DISABLE) {
            return classForName(classLoader, className);
        }

        long hash = MAGIC_HASH_CODE;
        for (int i = 0, typeNameLength = className.length(); i < typeNameLength; ++i) {
            char ch = className.charAt(i);
            if (ch == '$') {
                ch = '.';
            }
            hash ^= ch;

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Make the offending class (and any nested types) implement java.io.Serializable
  2. If the class is third-party and cannot be changed, set dubbo.application.serialize-check-status to DISABLE or WARN and check-serializable to false
  3. Verify the exact class name from the logged message and audit why it appears in the serialized stream

Example fix

// before
public class MyRequest {
    private String id;
}
// after
public class MyRequest implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    private String id;
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = MyDto.class;
if (!java.io.Serializable.class.isAssignableFrom(c)) {
    // do not send c over RPC; mark it Serializable or exclude it
}

Type guard

static boolean isRpcSafe(Class<?> c) {
    return java.io.Serializable.class.isAssignableFrom(c);
}

Try / catch

try { /* rpc call */ } catch (IllegalArgumentException e) { if (e.getMessage().contains("Serializable")) { /* mark class Serializable */ } }

Prevention

When it happens

Trigger: An RPC payload references a non-Serializable class (no 'implements Serializable' on the class or its hierarchy) while the framework is in strict Serializable-checking mode.

Common situations: Sharing a DTO/exception/enum across provider and consumer where the class was never marked Serializable; third-party library objects injected into a payload; upgrading Dubbo to a version that enables checkSerializable by default.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/141c3b1643e4a10d. Report an issue: GitHub.