microsoft/FASTER · error · InvalidOperationException

AsyncReadRecordObjectsToMemory invalid for…

Error message

AsyncReadRecordObjectsToMemory invalid for BlittableAllocator

What it means

VarLenBlittableAllocator stores records inline in sector-aligned memory pages and never keeps key/value objects in an object log, so the asynchronous object-deserialization read path is meaningless for it. The allocator deliberately overrides AsyncReadRecordObjectsToMemory to throw InvalidOperationException as an internal misuse guard. This indicates the caller expected an IObjectAllocator-style read path on a blittable allocator.

Solutions

  1. Use the direct (blittable) read path — records live in memory pages, so read them via ReadAsync/AsyncReadRecord to memory and copy bytes, not via the objects API.
  2. If you need key/value heap objects, use VarlenBlittableFetchAsync/GetNext-style APIs (or ConvertToRecord) on the scan iterator instead of the objects read path.
  3. Re-check generic constraints: the helper should be constrained to the object allocator type when it depends on AsyncReadRecordObjectsToMemory.
  4. This is an invariant violation — file a bug with a repro if it comes from stock FASTER APIs.

Example fix

// before: object-allocator style read against blittable log
allocator.AsyncReadRecordObjectsToMemory(fromLogical, numBytes, callback, context, result);
// after: direct blittable read
var status = await fkv.ReadAsync(ref key, ref input, ref output, ctx, serialFn, sessionId);
Defensive patterns

Strategy: validation

Validate before calling

// ensure the allocator is not blittable before using object-read APIs
if (allocator is VarLenBlittableAllocator<Key, Value>)
    throw new NotSupportedException("Use direct blittable read path, not AsyncReadRecordObjectsToMemory");

Type guard

static bool IsBlittableAllocator<I, K, V>(BlittableAllocatorBase<I, K, V> a)
    => a is VarLenBlittableAllocator<K, V>;

Prevention

When it happens

Trigger: An async page-read continuation or ReadInternal path requests async object materialization (AsyncReadRecordObjectsToMemory) while hlog is a VarLenBlittableAllocator/FasterLog-style blittable store. This is usually reached through internal plumbing (e.g. epoch-resumed async IO continuation) rather than a user API, typically from a mis-typed generic instantiation or code written for ObjectAllocator<...> being run against blittable types.

Common situations: Writing custom session/scan code that calls allocator internals copied from an ObjectsAllocator sample; generic helpers parameterized to work with both blittable and object allocators that assume the object-read API exists; upgrading FASTER versions where the async path changed.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at cs/src/core/Allocator/VarLenBlittableAllocator.cs:433

            ulong alignedSourceAddress, int destinationPageIndex, uint aligned_read_length,
            DeviceIOCompletionCallback callback, PageAsyncReadResult<TContext> asyncResult, IDevice device, IDevice objlogDevice)
        {
            device.ReadAsync(alignedSourceAddress, (IntPtr)pointers[destinationPageIndex],
                aligned_read_length, callback, asyncResult);
        }

        /// <summary>
        /// Invoked by users to obtain a record from disk. It uses sector aligned memory to read 
        /// the record efficiently into memory.
        /// </summary>
        /// <param name="fromLogical"></param>
        /// <param name="numBytes"></param>
        /// <param name="callback"></param>
        /// <param name="context"></param>
        /// <param name="result"></param>
        protected override void AsyncReadRecordObjectsToMemory(long fromLogical, int numBytes, DeviceIOCompletionCallback callback, AsyncIOContext<Key, Value> context, SectorAlignedMemory result = default)
        {
            throw new InvalidOperationException("AsyncReadRecordObjectsToMemory invalid for BlittableAllocator");
        }

        /// <summary>
        /// Retrieve objects from object log
        /// </summary>
        /// <param name="record"></param>
        /// <param name="ctx"></param>
        /// <returns></returns>
        protected override bool RetrievedFullRecord(byte* record, ref AsyncIOContext<Key, Value> ctx)
        {
            return true;
        }

        public override ref Key GetContextRecordKey(ref AsyncIOContext<Key, Value> ctx)
        {
            return ref GetKey((long)ctx.record.GetValidPointer());
        }

View on GitHub (pinned to 321d872eab)