apache/flink · critical · IOException

The class {} is not a subclass of {}

Error message

The class {} is not a subclass of {}

What it means

After successfully loading the class named in a checkpoint's metadata via Class.forName, InstantiationUtil.resolveClassByName verifies it is a subtype of the expected supertype (e.g. TypeSerializerSnapshot). If supertype.isAssignableFrom(rawClazz) is false, this IOException is thrown, meaning the stored class exists but does not implement/extend what the restore code requires.

Source

Thrown at flink-core/src/main/java/org/apache/flink/util/InstantiationUtil.java:673

        final String className = in.readUTF();
        final Class<?> rawClazz;
        try {
            rawClazz = Class.forName(className, false, cl);
        } catch (ClassNotFoundException e) {
            String error = "Could not find class '" + className + "' in classpath.";
            if (className.contains("SerializerConfig")) {
                error +=
                        " TypeSerializerConfigSnapshot and it's subclasses are not supported since Flink 1.17."
                                + " If you are using built-in serializers, please first migrate to Flink 1.16."
                                + " If you are using custom serializers, please migrate them to"
                                + " TypeSerializerSnapshot using Flink 1.16.";
            }
            throw new IOException(error, e);
        }

        if (!supertype.isAssignableFrom(rawClazz)) {
            throw new IOException(
                    "The class " + className + " is not a subclass of " + supertype.getName());
        }

        @SuppressWarnings("unchecked")
        Class<T> clazz = (Class<T>) rawClazz;
        return clazz;
    }

    // --------------------------------------------------------------------------------------------

    /** Private constructor to prevent instantiation. */
    private InstantiationUtil() {
        throw new RuntimeException();
    }
}

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Read the two class names in the message: the stored class and the expected supertype, then check why the subtype relation is broken (usually the removed TypeSerializerConfigSnapshot API).
  2. If upgrading across 1.17: perform an intermediate restore on Flink 1.16 with serializers already migrated to TypeSerializerSnapshot, then take a new savepoint.
  3. Fix the custom class so it implements the expected interface (e.g. TypeSerializerSnapshot) and rebuild the user jar.
  4. Check for duplicate/legacy jars on the classpath that shadow the correct snapshot class.

Example fix

// before
public class MySnapshot extends SimpleTypeSerializerSnapshot<MyType> {} // but class in jar v1 implements TypeSerializerConfigSnapshot

// after: ensure the snapshot class on the runtime classpath implements the required supertype
public class MySnapshot extends SimpleTypeSerializerSnapshot<MyType> {
    public MySnapshot() { super(MySerializer::new); }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> stored = Class.forName(snapshotClassName, false, cl);
if (!TypeSerializerSnapshot.class.isAssignableFrom(stored)) {
    throw new IllegalStateException(snapshotClassName + " does not implement TypeSerializerSnapshot; checkpoint format predates Flink 1.17 - migrate via 1.16");
}

Prevention

When it happens

Trigger: Restoring a checkpoint/savepoint where the serializer snapshot class name resolves to an existing class, but that class does not implement the required interface — typically an old TypeSerializerConfigSnapshot subclass being checked against TypeSerializerSnapshot, or a refactored class that changed its type hierarchy.

Common situations: Flink upgrade from 1.x to 1.17+ where the old snapshot class is still on the classpath but implements the removed API; a user refactored a custom serializer snapshot so it no longer implements TypeSerializerSnapshot; two versions of a class in different jars and the wrong one wins classloading.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/fc693b183ffc0a31. Report an issue: GitHub.