apache/flink · error · RuntimeException

Cannot initialize fields.

Error message

Cannot initialize fields.

What it means

PojoSerializer.initializeFields() iterates every POJO field and sets it to a default instance produced by the field's own TypeSerializer.createInstance(). This RuntimeException is thrown when Field.set() raises an IllegalAccessException — meaning the JVM refused the reflective write even though the field was previously made accessible. It indicates an access-control or encapsulation barrier, not a missing constructor.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/PojoSerializer.java:247

    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) {
                try {
                    fields[i].set(t, fieldSerializers[i].createInstance());
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("Cannot initialize fields.", e);
                }
            }
        }
    }

    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public T copy(T from) {
        if (from == null) {
            return null;
        }

        Class<?> actualType = from.getClass();
        if (isRecord()) {
            try {
                JavaRecordBuilderFactory<T>.JavaRecordBuilder builder = recordFactory.newBuilder();
                for (int i = 0; i < numFields; i++) {
                    if (fields[i] != null) {

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. If using Java modules, add 'opens your.package to org.apache.flink.core' in module-info.java (or launch with --add-opens).
  2. Remove the 'final' modifier from POJO fields that the serializer must write, or ensure the serializer does not need to initialize them (they are already non-null after construction).
  3. Provide a TypeSerializerSnapshot / custom serializer so Flink does not rely on reflective field writes.
  4. Verify that no SecurityManager or custom classloader is blocking reflective access.
  5. As a last resort, annotate the type for Kryo serialization to bypass POjoSerializer entirely.

Example fix

// before — final field in a sealed module; Field.set throws IllegalAccessException
public class Sensor {
    public final String id;   // final + not open → reflective write denied
    public Sensor() { this.id = ""; }
}

// after — remove final so the serializer can write the field at restore time
public class Sensor {
    public String id;
    public Sensor() { this.id = ""; }
}
Defensive patterns

Strategy: validation

Validate before calling

// Check that all non-static fields of the POJO are reflectively writable
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public static List<String> nonWritableFields(Class<?> clazz) {
    List<String> bad = new ArrayList<>();
    for (Field f : clazz.getDeclaredFields()) {
        int mod = f.getModifiers();
        if (Modifier.isStatic(mod)) continue;
        try {
            f.setAccessible(true);
            // final fields may still reject set() on some JVMs
            if (Modifier.isFinal(mod)) bad.add(f.getName() + " (final)");
        } catch (SecurityException e) {
            bad.add(f.getName() + " (inaccessible)");
        }
    }
    return bad;
}

Try / catch

// initializeFields is called internally; guard at the type-registration level
List<String> bad = nonWritableFields(MyPojo.class);
if (!bad.isEmpty()) {
    throw new IllegalStateException(
        "Fields not writable by PojoSerializer: " + bad
        + " — remove 'final' or open the module");
}

Prevention

When it happens

Trigger: After the POJO is successfully constructed via instantiateRaw(), initializeFields() calls fields[i].set(t, fieldSerializers[i].createInstance()). If the reflective set is denied, IllegalAccessException is caught and re-thrown with this message.

Common situations: The field is final and the JVM version enforces reflective-write restrictions on final fields; the POJO class is in a named module whose package is not 'open' to Flink, so setAccessible(true) silently fails or Field.set is rejected at call time; a security manager denies reflective field modification. This is rarer than errors 660/661 because fields are made accessible during serializer setup, but module-system tightening (Java 16+ strong encapsulation by default) makes it increasingly common.

Related errors


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