microsoft/FASTER · error · FasterException

Physical pointer returned by allocator: de-reference…

Error message

Physical pointer returned by allocator: de-reference pointer to set records instead of calling Set (otherwise, set ForceUnpinnedAllocation to true)

What it means

Same family as Get: when MallocFixedPageSize is in physical-address mode (ReturnPhysicalAddress), Set(long index, ref T value) is disabled because writes must go through the raw pointer, and record pinning is managed by the heap container. Calling Set throws FasterException; either dereference the physical address to write, or configure ForceUnpinnedAllocation if pinned physical pointers are not used.

Solutions

  1. Write via the physical pointer: *(T*)allocator.GetPhysicalAddress(index) = value; (or Unsafe.As/ref dereference)
  2. Set ForceUnpinnedAllocation = true in the allocator configuration if unpinning is intended and Set should be allowed
  3. Reconfigure the allocator with ReturnPhysicalAddress = false when Set/Get object access is required
  4. Update shared write helpers to branch on allocator mode like read helpers

Example fix

// before
allocator.Set(index, ref newValue);
// after
if (allocator.ReturnPhysicalAddress)
{
    *(T*)allocator.GetPhysicalAddress(index) = newValue;
}
else
{
    allocator.Set(index, ref newValue);
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Check allocator mode before writing
if (allocator.ReturnPhysicalAddress)
    *(T*)allocator.GetPhysicalAddress(index) = value;
else
    allocator.Set(index, ref value);

Type guard

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

Try / catch

try
{
    allocator.Set(index, ref value);
}
catch (FasterException ex) when (ex.Message.Contains("Physical pointer returned by allocator"))
{
    *(T*)allocator.GetPhysicalAddress(index) = value;
}

Prevention

When it happens

Trigger: Calling allocator.Set(index, ref value) on a ReturnPhysicalAddress = true MallocFixedPageSize; seen in tests/code like BasicIHeapContainerMallocFPSTest paths that write through IHeapContainer against physical-address allocators.

Common situations: Reusing Set()-based write helpers after enabling physical-address mode; writing to allocator slots directly in custom heap containers or recovery code without dereferencing pointers.

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/c6b90c82413160d7. Report an issue: GitHub.

Appendix: source

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

        [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;
        }

        /// <summary>
        /// Free object
        /// </summary>
        /// <param name="pointer"></param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Free(long pointer)
        {
            if (!ReturnPhysicalAddress)
                values[pointer >> PageSizeBits][pointer & PageSizeMask] = default;
            freeList.Enqueue(pointer);
        }

        internal int FreeListCount => freeList.Count;   // For test

View on GitHub (pinned to 321d872eab)