{"record":{"id":"37fa4b50cc1f81ce","repo":"apache/flink","slug":"serializer-not-yet-initialized-37fa4b","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/MapStateDescriptor.java","lineNumber":96,"sourceCode":"     * consider using the {@link #MapStateDescriptor(String, TypeInformation, TypeInformation)}\n     * constructor.\n     *\n     * @param name The name of the {@code MapStateDescriptor}.\n     * @param keyClass The class of the type of keys in the state.\n     * @param valueClass The class of the type of values in the state.\n     */\n    public MapStateDescriptor(String name, Class<UK> keyClass, Class<UV> valueClass) {\n        super(name, valueClass);\n        this.userKeySerializer = new StateSerializerReference<>(keyClass);\n    }\n\n    @Nonnull\n    public TypeSerializer<UK> getUserKeySerializer() {\n        TypeSerializer<UK> serializer = userKeySerializer.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<UK> getUserKeyTypeInformation() {\n        return userKeySerializer.getTypeInformation();\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     */\n    @Override\n    public boolean isSerializerInitialized() {","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/state/v2/MapStateDescriptor.java#L78-L114","documentation":"MapStateDescriptor v2 getUserKeySerializer() returns serializer.duplicate() from the userKeySerializer StateSerializerReference, but the reference is still empty because the descriptor's serializers have not been initialized. The v2 descriptors (package state.v2) initialize lazily via initializeSerializerUnlessSet(ExecutionConfig), mirroring the v1 contract. Calling getUserKeySerializer before initialization violates that contract.","triggerScenarios":"Using the DataStream v2 API (flink-datastream-api) and calling getUserKeySerializer() on a MapStateDescriptor before the runtime has called initializeSerializerUnlessSet; in tests that construct a v2 descriptor and immediately pull the key serializer.","commonSituations":"Early adoption of DataStream v2 where documentation or examples pull serializers eagerly; custom v2 operators that need the key serializer before open(); test scaffolding that skips the initialization step.","solutions":["Call mapStateDescriptor.initializeSerializerUnlessSet(executionConfig) with the ExecutionConfig (from the v2 environment or RuntimeContext) before getUserKeySerializer().","Read the key serializer inside the operator's open()/initialize lifecycle hook, not at descriptor construction.","In tests, call initializeSerializerUnlessSet(new ExecutionConfig()) right after constructing the descriptor."],"exampleFix":"// before\nMapStateDescriptor<String,Integer> desc =\n    new MapStateDescriptor<>(\"m\", String.class, Integer.class);\nTypeSerializer<String> ks = desc.getUserKeySerializer(); // throws\n\n// after\nMapStateDescriptor<String,Integer> desc =\n    new MapStateDescriptor<>(\"m\", String.class, Integer.class);\ndesc.initializeSerializerUnlessSet(env.getConfig());\nTypeSerializer<String> ks = desc.getUserKeySerializer();","handlingStrategy":"validation","validationCode":"if (!mapStateDescriptor.isSerializerInitialized()) {\n    mapStateDescriptor.initializeSerializerUnlessSet(\n        getRuntimeContext().getExecutionConfig());\n}\nTypeSerializer<UK> ks = mapStateDescriptor.getUserKeySerializer();","typeGuard":"// Guard getUserKeySerializer with the v2 initialization check\nif (!desc.isSerializerInitialized()) {\n    desc.initializeSerializerUnlessSet(executionConfig);\n}","tryCatchPattern":"try {\n    return desc.getUserKeySerializer();\n} catch (IllegalStateException e) {\n    desc.initializeSerializerUnlessSet(cfg);\n    return desc.getUserKeySerializer();\n}","preventionTips":["Initialize v2 descriptors in open()/initialize before any serializer access.","Unit-test getUserKeySerializer after wiring the descriptor and ExecutionConfig.","Keep v2 descriptor construction and initialization in the same lifecycle method."],"tags":["state-descriptor-v2","map-state","serializer","lazy-initialization"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}