apache/flink · error · IllegalStateException

Serializer not yet initialized.

Error message

Serializer not yet initialized.

What it means

StateDescriptor v2 (package state.v2) getSerializer() returns serializer.duplicate() from the internal typeSerializer StateSerializerReference, which is empty until initializeSerializerUnlessSet(ExecutionConfig) runs. The v2 descriptor deliberately defers serializer creation so it can incorporate ExecutionConfig-driven serializer configuration. Invoking getSerializer before initialization throws.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/state/v2/StateDescriptor.java:135

    }

    @Nonnull
    public StateTtlConfig getTtlConfig() {
        return ttlConfig;
    }

    @Nonnull
    public String getStateId() {
        return stateId;
    }

    @Nonnull
    public TypeSerializer<T> getSerializer() {
        TypeSerializer<T> serializer = typeSerializer.get();
        if (serializer != null) {
            return serializer.duplicate();
        } else {
            throw new IllegalStateException("Serializer not yet initialized.");
        }
    }

    @Internal
    @Nullable
    public TypeInformation<T> getTypeInformation() {
        return typeSerializer.getTypeInformation();
    }

    // ------------------------------------------------------------------------

    /**
     * Checks whether the serializer has been initialized. Serializer initialization is lazy, to
     * allow parametrization of serializers with an {@link ExecutionConfig} via {@link
     * #initializeSerializerUnlessSet(ExecutionConfig)}.
     *
     * @return True if the serializers have been initialized, false otherwise.
     */

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Call descriptor.initializeSerializerUnlessSet(executionConfig) before getSerializer(), using the ExecutionConfig from the v2 environment.
  2. Defer getSerializer to the operator open()/initialize phase where the runtime guarantees initialization.
  3. In tests, call initializeSerializerUnlessSet(new ExecutionConfig()) immediately after building the descriptor.

Example fix

// before
ValueStateDescriptor<Long> desc = new ValueStateDescriptor<>("v", Long.class);
TypeSerializer<Long> ser = desc.getSerializer(); // throws

// after
ValueStateDescriptor<Long> desc = new ValueStateDescriptor<>("v", Long.class);
desc.initializeSerializerUnlessSet(env.getConfig());
TypeSerializer<Long> ser = desc.getSerializer();
Defensive patterns

Strategy: validation

Validate before calling

if (!descriptor.isSerializerInitialized()) {
    descriptor.initializeSerializerUnlessSet(
        getRuntimeContext().getExecutionConfig());
}
TypeSerializer<T> ser = descriptor.getSerializer();

Type guard

static <T> TypeSerializer<T> safeGet(StateDescriptor<T> d, ExecutionConfig cfg) {
    if (!d.isSerializerInitialized()) d.initializeSerializerUnlessSet(cfg);
    return d.getSerializer();
}

Try / catch

try {
    return descriptor.getSerializer();
} catch (IllegalStateException e) {
    descriptor.initializeSerializerUnlessSet(cfg);
    return descriptor.getSerializer();
}

Prevention

When it happens

Trigger: Calling getSerializer() on a v2 StateDescriptor subclass (ValueStateDescriptor, ListStateDescriptor, etc. from flink-datastream-api) before the runtime initializes it; in user code or tests outside the normal open() lifecycle.

Common situations: DataStream v2 adoption where serializer access happens before state registration; custom v2 source/sink operators that touch the serializer during setup; unit tests constructing descriptors without running the initialization hook.

Related errors


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