{"record":{"id":"ccb9a634521e092e","repo":"apache/flink","slug":"serializer-not-yet-initialized-ccb9a6","errorCode":null,"errorMessage":"Serializer not yet initialized.","messagePattern":"Serializer not yet initialized\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/state/v2/StateDescriptor.java","lineNumber":135,"sourceCode":"    }\n\n    @Nonnull\n    public StateTtlConfig getTtlConfig() {\n        return ttlConfig;\n    }\n\n    @Nonnull\n    public String getStateId() {\n        return stateId;\n    }\n\n    @Nonnull\n    public TypeSerializer<T> getSerializer() {\n        TypeSerializer<T> serializer = typeSerializer.get();\n        if (serializer != null) {\n            return serializer.duplicate();\n        } else {\n            throw new IllegalStateException(\"Serializer not yet initialized.\");\n        }\n    }\n\n    @Internal\n    @Nullable\n    public TypeInformation<T> getTypeInformation() {\n        return typeSerializer.getTypeInformation();\n    }\n\n    // ------------------------------------------------------------------------\n\n    /**\n     * Checks whether the serializer has been initialized. Serializer initialization is lazy, to\n     * allow parametrization of serializers with an {@link ExecutionConfig} via {@link\n     * #initializeSerializerUnlessSet(ExecutionConfig)}.\n     *\n     * @return True if the serializers have been initialized, false otherwise.\n     */","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/state/v2/StateDescriptor.java#L117-L153","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call descriptor.initializeSerializerUnlessSet(executionConfig) before getSerializer(), using the ExecutionConfig from the v2 environment.","Defer getSerializer to the operator open()/initialize phase where the runtime guarantees initialization.","In tests, call initializeSerializerUnlessSet(new ExecutionConfig()) immediately after building the descriptor."],"exampleFix":"// before\nValueStateDescriptor<Long> desc = new ValueStateDescriptor<>(\"v\", Long.class);\nTypeSerializer<Long> ser = desc.getSerializer(); // throws\n\n// after\nValueStateDescriptor<Long> desc = new ValueStateDescriptor<>(\"v\", Long.class);\ndesc.initializeSerializerUnlessSet(env.getConfig());\nTypeSerializer<Long> ser = desc.getSerializer();","handlingStrategy":"validation","validationCode":"if (!descriptor.isSerializerInitialized()) {\n    descriptor.initializeSerializerUnlessSet(\n        getRuntimeContext().getExecutionConfig());\n}\nTypeSerializer<T> ser = descriptor.getSerializer();","typeGuard":"static <T> TypeSerializer<T> safeGet(StateDescriptor<T> d, ExecutionConfig cfg) {\n    if (!d.isSerializerInitialized()) d.initializeSerializerUnlessSet(cfg);\n    return d.getSerializer();\n}","tryCatchPattern":"try {\n    return descriptor.getSerializer();\n} catch (IllegalStateException e) {\n    descriptor.initializeSerializerUnlessSet(cfg);\n    return descriptor.getSerializer();\n}","preventionTips":["Always initialize v2 descriptors before reading serializers.","Keep serializer access inside open()/initialize hooks.","Add tests that exercise the serializer after initialization."],"tags":["state-descriptor-v2","serializer","lazy-initialization"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}