apache/flink · error · IllegalStateException

Unexpected serializer type.

Error message

Unexpected serializer type.

What it means

Thrown by MapStateDescriptor.getKeySerializer() when the state's serializer is not a MapSerializer. The method assumes the underlying serializer wraps a key serializer and a value serializer; if a custom or incompatible serializer was injected (e.g. via setStateSerializer or a config override), the cast to MapSerializer would be unsafe, so an explicit instanceof guard throws instead. This indicates the state descriptor's serializer was replaced after construction.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/state/MapStateDescriptor.java:105

     */
    public MapStateDescriptor(String name, Class<UK> keyClass, Class<UV> valueClass) {
        super(name, new MapTypeInfo<>(keyClass, valueClass), null);
    }

    @Override
    public Type getType() {
        return Type.MAP;
    }

    /**
     * Gets the serializer for the keys in the state.
     *
     * @return The serializer for the keys in the state.
     */
    public TypeSerializer<UK> getKeySerializer() {
        final TypeSerializer<Map<UK, UV>> rawSerializer = getSerializer();
        if (!(rawSerializer instanceof MapSerializer)) {
            throw new IllegalStateException("Unexpected serializer type.");
        }

        return ((MapSerializer<UK, UV>) rawSerializer).getKeySerializer();
    }

    /**
     * Gets the serializer for the values in the state.
     *
     * @return The serializer for the values in the state.
     */
    public TypeSerializer<UV> getValueSerializer() {
        final TypeSerializer<Map<UK, UV>> rawSerializer = getSerializer();
        if (!(rawSerializer instanceof MapSerializer)) {
            throw new IllegalStateException("Unexpected serializer type.");
        }

        return ((MapSerializer<UK, UV>) rawSerializer).getValueSerializer();
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Ensure the MapStateDescriptor uses the default MapSerializer (do not override the serializer for map state).
  2. If restoring from a savepoint, verify the serializer snapshot is compatible with MapSerializer or re-register the correct serializer.
  3. If you need a custom serializer, access the raw serializer via getSerializer() instead of getKeySerializer().

Example fix

// before: custom serializer override breaks getKeySerializer
descriptor.initializeSerializerUnlessSet(() -> new CustomTypeSerializer<>());
descriptor.getKeySerializer(); // throws IllegalStateException

// after: let the descriptor build its own MapSerializer
descriptor.getKeySerializer(); // returns MapSerializer's key serializer
Defensive patterns

Strategy: type-guard

Validate before calling

TypeSerializer<?> ser = descriptor.getSerializer();
if (!(ser instanceof MapSerializer)) {
    throw new IllegalStateException(
        "Cannot get key serializer: underlying serializer is " + ser.getClass().getName());
}

Type guard

public static boolean hasMapSerializer(MapStateDescriptor<?, ?> desc) {
    return desc.getSerializer() instanceof MapSerializer;
}

Try / catch

try {
    return descriptor.getKeySerializer();
} catch (IllegalStateException e) {
    // fall back to raw serializer access
    return descriptor.getSerializer();
}

Prevention

When it happens

Trigger: Calling getKeySerializer() after the descriptor's serializer was overridden with a non-MapSerializer (e.g. a custom TypeSerializer injected via a StateBackend config or a restore from a savepoint with an incompatible serializer snapshot).

Common situations: Restoring a MapState from a savepoint whose serializer snapshot resolved to a non-map serializer; injecting a custom serializer via the state backend configuration; using a state backend that substitutes serializers internally.

Related errors


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