apache/flink · error · InvalidProgramException

Object {obj} is not serializable

Error message

Object {obj} is not serializable

What it means

Thrown by ClosureCleaner.ensureSerializable() when InstantiationUtil.serializeObject(obj) fails for any reason. This is the generic, no-diagnostic variant: the object could not be Java-serialized. Unlike error 541 this message does not indicate a specific cause; the chained exception (NotSerializableException) names the offending class.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/ClosureCleaner.java:211

            cls.getDeclaredMethod("writeObject", ObjectOutputStream.class);
            return true;
        } catch (NoSuchMethodException ignored) {
        }

        try {
            cls.getDeclaredMethod("writeReplace");
            return true;
        } catch (NoSuchMethodException ignored) {
        }

        return Externalizable.class.isAssignableFrom(cls);
    }

    public static void ensureSerializable(Object obj) {
        try {
            InstantiationUtil.serializeObject(obj);
        } catch (Exception e) {
            throw new InvalidProgramException("Object " + obj + " is not serializable", e);
        }
    }

    private static boolean cleanThis0(Object func, Class<?> cls, String this0Name) {

        This0AccessFinder this0Finder = new This0AccessFinder(this0Name);
        getClassReader(cls).accept(this0Finder, 0);

        final boolean accessesClosure = this0Finder.isThis0Accessed();

        if (LOG.isDebugEnabled()) {
            LOG.debug(this0Name + " is accessed: " + accessesClosure);
        }

        if (!accessesClosure) {
            Field this0;
            try {
                this0 = func.getClass().getDeclaredField(this0Name);

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Read the chained NotSerializableException to find the offending class name.
  2. Make the offending field transient and reconstruct it in the RichFunction.open() lifecycle hook.
  3. Ensure all fields on the function are themselves Serializable or primitives.
  4. Replace the offending object with a serializable descriptor (e.g. store connection params as Strings, build the connection in open()).

Example fix

// before
public class BadMapper implements MapFunction<String,String> {
  private Connection db; // java.sql.Connection is NOT serializable
}

// after
public class GoodMapper extends RichMapFunction<String,String> {
  private transient Connection db;
  private final String url; // serializable descriptor
  public void open(Configuration c) throws Exception { db = DriverManager.getConnection(url); }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Proactive serialization check
private static void ensureSerializable(Object o) {
    try {
        org.apache.flink.util.InstantiationUtil.serializeObject(o);
    } catch (java.io.NotSerializableException e) {
        throw new IllegalArgumentException("Non-serializable field on " + o.getClass(), e);
    }
}

Try / catch

try {
    org.apache.flink.api.java.ClosureCleaner.ensureSerializable(func);
} catch (org.apache.flink.api.common.InvalidProgramException e) {
    Throwable cause = e.getCause(); // NotSerializableException names the offending class
    throw new RuntimeException("Make offending fields transient or Serializable: " + cause, e);
}

Prevention

When it happens

Trigger: Direct call to ClosureCleaner.ensureSerializable(obj), or the final check in clean() when closureAccessed is false but the object still fails serialization. Any function/object passed to a DataStream operation that contains or references a non-serializable field (e.g. a Thread, Socket, JDBC Connection, SparkContext, raw lambda capturing a non-serializable local).

Common situations: A function holds a non-transient field of a non-serializable type (logger with state, DB client, config object from a framework); a lambda captures a local variable of a non-serializable type; passing an object graph that transitively reaches a system resource.

Related errors


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