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
- 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.
- If you need key/value heap objects, use VarlenBlittableFetchAsync/GetNext-style APIs (or ConvertToRecord) on the scan iterator instead of the objects read path.
- Re-check generic constraints: the helper should be constrained to the object allocator type when it depends on AsyncReadRecordObjectsToMemory.
- 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
- Do not call allocator internals; use Fkv.ReadAsync and iterator APIs
- Constrain generic helpers to the allocator type whose APIs they use
- When sharing code between object and blittable allocators, branch on allocator type first
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
- BlittableAllocator memory pages are sector aligned - use…
- AsyncReadRecordObjectsToMemory invalid for…
- BlittableAllocator memory pages are sector aligned - use…
- Incremental snapshots not supported with generic allocator
- Pending reads not supported with pub/sub
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)