apache/flink · error · KryoException

Error during Java serialization.

Error message

Error during Java serialization.

What it means

JavaSerializer is a Kryo serializer shim that delegates to Java's native ObjectOutputStream. On write() it lazily creates an ObjectOutputStream wrapped over Kryo's Output (cached in the Kryo graph context) and calls writeObject(o). Any failure from Java serialization — most commonly the object graph containing a non-Serializable element, or a writeObject method throwing — surfaces as a KryoException saying 'Error during Java serialization.'.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/kryo/JavaSerializer.java:63

 */
public class JavaSerializer<T> extends Serializer<T> {

    public JavaSerializer() {}

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public void write(Kryo kryo, Output output, T o) {
        try {
            ObjectMap graphContext = kryo.getGraphContext();
            ObjectOutputStream objectStream = (ObjectOutputStream) graphContext.get(this);
            if (objectStream == null) {
                objectStream = new ObjectOutputStream(output);
                graphContext.put(this, objectStream);
            }
            objectStream.writeObject(o);
            objectStream.flush();
        } catch (Exception ex) {
            throw new KryoException("Error during Java serialization.", ex);
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public T read(Kryo kryo, Input input, Class aClass) {
        try {
            ObjectMap graphContext = kryo.getGraphContext();
            ObjectInputStream objectStream = (ObjectInputStream) graphContext.get(this);
            if (objectStream == null) {
                // make sure we use Kryo's classloader
                objectStream =
                        new InstantiationUtil.ClassLoaderObjectInputStream(
                                input, kryo.getClassLoader());
                graphContext.put(this, objectStream);
            }
            return (T) objectStream.readObject();
        } catch (Exception ex) {

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Make the offending class and every referenced field implement java.io.Serializable (mark non-data fields transient).
  2. Register a proper Kryo serializer for the problematic type (KryoSerializationSchema / env.registerTypeWithKryo or Serializers.registerSerializer) so JavaSerializer is not used.
  3. Inspect the chained cause in the KryoException (NotSerializableException names the first non-serializable class) and fix that specific field.
  4. For fields that cannot be serialized, restructure them as transient plus re-derivation on readObject, or use a custom Kryo Serializer that writes only the logical state.

Example fix

// before
public class JobContext {
    private Connection conn; // not serializable -> JavaSerializer fails
}

// after
public class JobContext implements java.io.Serializable {
    private transient Connection conn;
    private String connUrl;
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        conn = connect(connUrl); // re-derive on deserialize
    }
}
Defensive patterns

Strategy: validation

Validate before calling

static void assertSerializable(Object sample) {
    try (java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
         java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(bos)) {
        oos.writeObject(sample);
    } catch (java.io.IOException e) {
        throw new IllegalStateException("Value fails Java serialization: " + e.getMessage(), e);
    }
}

Try / catch

try {
    kryo.writeClassAndObject(output, record);
} catch (com.esotericsoftware.kryo.KryoException e) {
    Throwable cause = e.getCause();
    if (cause instanceof java.io.NotSerializableException) {
        // log which class is not serializable, fix model, fail job
    }
    throw e;
}

Prevention

When it happens

Trigger: Kryo serializing an object with JavaSerializer (e.g. registered via Serializers.registerSerWithKryo or a type falling back to JavaSerializer) where the object or a nested field is not java.io.Serializable; a custom writeObject/ObjectOutputStream putFields mismatch; a field's type changing incompatibly between write and read; stream corruption from mixed serializers.

Common situations: Classes used in Flink data streams or in Kryo-serialized state that implement Serializable only partially (fields of non-serializable types like Thread, InputStream, or third-party objects without a Kryo serializer registered); upgrading a class and restoring old state; closures capturing non-serializable resources.

Related errors


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