microsoft/FASTER · error · FasterException

Physical pointer returned by allocator: de-reference…

Error message

Physical pointer returned by allocator: de-reference pointer to get records instead of calling Get

What it means

MallocFixedPageSize can be configured (ReturnPhysicalAddress) to hand out raw physical pointers for high-performance access. When that mode is on, calling Get(long index) would bypass the pointer indirection the allocator expects, so the method deliberately throws FasterException. Callers must instead de-reference the physical address (GetPhysicalAddress) to obtain a ref T.

Solutions

  1. Replace Get(index) with GetPhysicalAddress(index) and de-reference: ref var record = ref *(T*)allocator.GetPhysicalAddress(index)
  2. Set ForceUnpinnedAllocation / construct MallocFixedPageSize with ReturnPhysicalAddress = false if you need Get/Set object access
  3. Branch on allocator mode in shared code: use physical dereference when ReturnPhysicalAddress is true, else Get()

Example fix

// before
ref T record = ref allocator.Get(index);
// after
if (allocator.ReturnPhysicalAddress)
{
    ref T record = ref Unsafe.As<T, T>(ref *(T*)allocator.GetPhysicalAddress(index));
}
else
{
    ref T record = ref allocator.Get(index);
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Check allocator mode before choosing access pattern
if (allocator.ReturnPhysicalAddress)
    ref var r = ref *(T*)allocator.GetPhysicalAddress(index);
else
    ref var r = ref allocator.Get(index);

Type guard

static bool UsesPhysicalAddress(MallocFixedPageSize<T> a) => a.ReturnPhysicalAddress;

Try / catch

try
{
    ref var record = ref allocator.Get(index);
}
catch (FasterException ex) when (ex.Message.Contains("Physical pointer returned by allocator"))
{
    ref var record = ref Unsafe.AsRef<T>((void*)allocator.GetPhysicalAddress(index));
}

Prevention

When it happens

Trigger: Calling allocator.Get(index) on a MallocFixedPageSize instance constructed with ReturnPhysicalAddress = true; typically from helper code like valueRef paths or generic code that assumes object-mode allocators.

Common situations: Users switching allocator configuration to physical-address mode for performance and reusing existing Get()-based access code; shared utility functions written against object-mode allocators run against physical-address allocators.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at cs/src/core/Allocator/MallocFixedPageSize.cs:174

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public long GetPhysicalAddress(long logicalAddress)
        {
            Debug.Assert(isPinned, "GetPhysicalAddress requires pinning");
            if (ReturnPhysicalAddress)
                return logicalAddress;
            return (long)pointers[logicalAddress >> PageSizeBits] + (logicalAddress & PageSizeMask) * RecordSize;
        }

        /// <summary>
        /// Get object
        /// </summary>
        /// <param name="index">The index of the allocation. For BulkAllocate, this may be a value within the chunk size, to reference that particular record.</param>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ref T Get(long index)
        {
            if (ReturnPhysicalAddress)
                throw new FasterException("Physical pointer returned by allocator: de-reference pointer to get records instead of calling Get");
            Debug.Assert(index != kInvalidAllocationIndex, "Invalid allocation index");
            return ref values[index >> PageSizeBits][index & PageSizeMask];
        }

        /// <summary>
        /// Set object
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Set(long index, ref T value)
        {
            if (ReturnPhysicalAddress)
                throw new FasterException("Physical pointer returned by allocator: de-reference pointer to set records instead of calling Set (otherwise, set ForceUnpinnedAllocation to true)");
            Debug.Assert(index != kInvalidAllocationIndex, "Invalid allocation index");
            values[index >> PageSizeBits][index & PageSizeMask] = value;
        }

View on GitHub (pinned to 321d872eab)