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
- Read the chained NotSerializableException to find the offending class name.
- Make the offending field transient and reconstruct it in the RichFunction.open() lifecycle hook.
- Ensure all fields on the function are themselves Serializable or primitives.
- 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
- Mark non-serializable fields transient and rebuild them in open().
- Keep only Serializable/primitive fields on functions.
- Unit-test serialization of every UDF class.
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
- The implementation of the {functionType} is not serializable
- Cannot deserialize and unwrap accumulators properly.
- Failed to serialize ExecutionPlan.
- Failed to deserialize coordination response
- Cannot deserialize and unwrap accumulators properly.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/2a09795daf913c77.
Report an issue: GitHub.