microsoft/FASTER · error · Exception

Cannot use BlittableParameterSerializer with non-blittable…

Error message

Cannot use BlittableParameterSerializer with non-blittable types - specify serializer explicitly

What it means

The BlittableParameterSerializer (FixedLenSerializer) is a static generic serializer that only works when Key, Value, Input, and Output are all blittable unmanaged types (directly copyable raw memory, no references). Its static constructor validates this at type initialization and throws if any type parameter is non-blittable, because the default wire format cannot safely serialize managed references.

Solutions

  1. Change Key/Value/Input/Output types to blittable unmanaged ones (e.g., long, int, fixed-size structs) if possible.
  2. Otherwise specify an explicit serializer that supports your types instead of the blittable default.
  3. If a struct is failing, make it unmanaged and blittable: use fixed-size fields/blittable primitive members, no references.

Example fix

// before: string value with blittable serializer
var session = new ClientSession<long, string, string, string>(..., new BlittableParameterSerializer<long, string, string, string>());

// after: explicit serializer for non-blittable types
var session = new ClientSession<long, string, string, string>(..., new MyStringSerializer());
Defensive patterns

Strategy: validation

Validate before calling

// returns true only for blittable-at-runtime candidate types
static bool IsBlittableSafe<T>() where T : unmanaged =>
    Unsafe.SizeOf<T>() > 0 && !typeof(T).IsGenericType; // combine with the library's IsBlittable check

// pre-flight before constructing the session
if (!IsBlittableSafe<Key>() || !IsBlittableSafe<Value>())
    throw new InvalidOperationException("Use an explicit ISerializer for non-blittable Key/Value");

Type guard

// narrow to blittable-supported sessions only
static bool IsBlittableSession<TK, TV, TI, TO>(ClientSession<TK, TV, TI, TO> s)
    where TK : unmanaged where TV : unmanaged where TI : unmanaged where TO : unmanaged
    => s != null;

Try / catch

try { CreateSession(); }
catch (TypeInitializationException ex) when (ex.InnerException?.Message.Contains("non-blittable") == true)
{
    CreateSessionWithExplicitSerializer();
}

Prevention

When it happens

Trigger: Declaring a client session/serializer with BlittableParameterSerializer where any of Key, Value, Input, Output contains reference-type fields (e.g., string, arrays) or non-blittable structs (bool arrays, generics with refs, DateTime-like layouts).

Common situations: Using string or a struct containing string as Key/Value with the default blittable serializer; migrating from a blittable long key to a Guid/string key without changing the serializer; forgetting to pass an explicit ISerializer for non-blittable types.

Related errors


AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15). Data as JSON: /api/errors/ba6ec1f2463dbe5d. Report an issue: GitHub.

Appendix: source

Thrown at cs/remote/src/FASTER.client/FixedLenSerializer.cs:27

namespace FASTER.client
{
    /// <summary>
    /// Client-side serializer for blittable types
    /// </summary>
    /// <typeparam name="Key">Key</typeparam>
    /// <typeparam name="Value">Value</typeparam>
    /// <typeparam name="Input">Input</typeparam>
    /// <typeparam name="Output">Output</typeparam>
    public unsafe struct FixedLenSerializer<Key, Value, Input, Output>  : IClientSerializer<Key, Value, Input, Output>
        where Key : unmanaged
        where Value : unmanaged
        where Input : unmanaged
        where Output : unmanaged
    {
        static FixedLenSerializer()
        {
            if (!IsBlittable<Key>() || !IsBlittable<Value>() || !IsBlittable<Input>() || !IsBlittable<Output>())
                throw new Exception("Cannot use BlittableParameterSerializer with non-blittable types - specify serializer explicitly");
        }

        /// <inheritdoc />
        public bool Write(ref Key k, ref byte* dst, int length)
        {
            if (length < Unsafe.SizeOf<Key>()) return false;
            Unsafe.AsRef<Key>(dst) = k;
            dst += Unsafe.SizeOf<Key>();
            return true;
        }

        /// <inheritdoc />
        public bool Write(ref Value v, ref byte* dst, int length)
        {
            if (length < Unsafe.SizeOf<Value>()) return false;
            Unsafe.AsRef<Value>(dst) = v;
            dst += Unsafe.SizeOf<Value>();
            return true;

View on GitHub (pinned to 321d872eab)