apache/flink · error · RuntimeException
Cannot instantiate class.
Error message
Cannot instantiate class.
What it means
PojoSerializer.createInstance() attempts to build a fresh POJO via reflection (no-arg constructor) and then populate each field with a default instance from its field serializer. This RuntimeException is the outer catch that wraps ANY failure during that two-step process — either raw instantiation failed or field initialization failed. The wrapped cause (getCause()) holds the specific reason (NoSuchMethodException, InvocationTargetException, IllegalAccessException, etc.).
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/PojoSerializer.java:225
if (!stateful) {
// as a small memory optimization, we can share the same object between instances
duplicateSerializers = serializers;
}
return (TypeSerializer<Object>[]) duplicateSerializers;
}
@Override
public T createInstance() {
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()) || isRecord()) {
return null;
}
try {
T t = instantiateRaw();
initializeFields(t);
return t;
} catch (Exception e) {
throw new RuntimeException("Cannot instantiate class.", e);
}
}
private T instantiateRaw() {
try {
if (constructor == null) {
constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
}
return constructor.newInstance();
} catch (Exception e) {
throw new RuntimeException("Cannot instantiate class.", e);
}
}
protected void initializeFields(T t) {
for (int i = 0; i < numFields; i++) {
if (fields[i] != null) {View on GitHub (pinned to 2f3c205e92)
Solutions
- Inspect the wrapped cause via exception.getCause() — it distinguishes 'no no-arg constructor' from 'constructor threw' from 'field init failed'.
- Add a public no-arg constructor to the POJO class (or at minimum an accessible private one — setAccessible is called).
- If the POJO genuinely cannot have a no-arg constructor, register a custom TypeSerializer or TypeSerializerSnapshot, or annotate the type so Flink falls back to Kryo/Avro serialization.
- Ensure the exact same JAR (including POJO class) is deployed on all TaskManagers and the JobManager.
- If the class was refactored/renamed between job versions, implement a TypeSerializerSnapshot migration or reset state from a clean savepoint.
Example fix
// before — POJO with no no-arg constructor
public class MyEvent {
private String id;
public MyEvent(String id) { this.id = id; }
}
// after — add a no-arg constructor for the serializer
public class MyEvent {
private String id;
public MyEvent() { this.id = ""; } // serializer calls this
public MyEvent(String id) { this.id = id; }
} Defensive patterns
Strategy: validation
Validate before calling
// Before using a POJO type, verify it has an accessible no-arg constructor
import java.lang.reflect.Constructor;
public static boolean hasNoArgConstructor(Class<?> clazz) {
try {
Constructor<?> c = clazz.getDeclaredConstructor();
c.setAccessible(true);
return true;
} catch (NoSuchMethodException | SecurityException e) {
return false;
}
}
// Usage in a test or pipeline setup
if (!hasNoArgConstructor(MyPojo.class)) {
throw new IllegalStateException(
"POJO " + MyPojo.class.getName() + " needs a no-arg constructor for PojoSerializer");
} Try / catch
try {
T instance = pojoSerializer.createInstance();
} catch (RuntimeException e) {
Throwable cause = e.getCause();
log.error("PojoSerializer.createInstance failed for {}: {}",
pojoSerializer.getClass().getName(), cause != null ? cause : e);
// cause is typically NoSuchMethodException, InvocationTargetException,
// or IllegalAccessException — handle accordingly
throw e;
} Prevention
- Add a public no-arg constructor to every POJO used as a Flink type.
- Write a unit test that asserts TypeInformation.of(MyPojo.class).createSerializer(config).createInstance() succeeds for every domain type.
- Avoid constructors with side effects or external dependencies.
- Run PojoSerializer tests after any class relocation or shading build step.
When it happens
Trigger: The Flink runtime calls TypeSerializer.createInstance() during keyed-state restoration, spill/reload of POJO data, or when the sort/hash infrastructure needs a scratch instance. The exception fires when the POJO class cannot be reflectively constructed or when a field serializer cannot produce a default value for one of the POJO's fields.
Common situations: POJO class has only parameterized constructors and no no-arg constructor; POJO class was relocated or shaded so the loaded class differs from the one the serializer snapshot expects; a nested POJO field type itself lacks a no-arg constructor; the POJO class is not on the TaskManager classpath after a JAR change; the constructor exists but throws internally (e.g., requires a dependency injected at construction time).
Related errors
- Field '{}' could not be accessed.
- Cannot initialize fields.
- Unrecognized version or corrupt state: {version}
- Corrupt data: Unexpected magic number %08X
- Cannot register null type class.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/33a0e3fb97116ef3.
Report an issue: GitHub.