microsoft/FASTER · error · ArgumentOutOfRangeException

elementIndex

Error message

elementIndex

What it means

ArgumentOutOfRangeException with the message "elementIndex" thrown by UnmanagedMemoryManager<T>.Pin when the requested elementIndex is negative or >= _length. Pin creates a MemoryHandle over raw unmanaged memory and validates the offset against the manager's length before computing the pointer.

Solutions

  1. Pin with an index within [0, length) as given at construction; use sliced Memory to pin subsections instead of absolute indices
  2. Pass element count, not byte size, when constructing UnmanagedMemoryManager
  3. Validate the index before calling Pin in perf-sensitive code paths

Example fix

// before
memory.Pin(byteOffset); // may exceed element count
// after
int elementIndex = (int)(byteOffset / sizeof(MyType));
if (elementIndex < 0 || elementIndex >= length) throw new ArgumentException(...);
memory.Pin(elementIndex);
Defensive patterns

Strategy: validation

Validate before calling

if (elementIndex >= 0 && elementIndex < length) manager.Memory.Pin(elementIndex); else throw new ArgumentOutOfRangeException(nameof(elementIndex));

Type guard

bool CanPin(UnmanagedMemoryManager<T> m, int i) => i >= 0 && i < m.Length;

Try / catch

try { return memory.Pin(i); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "elementIndex")
{ throw new ArgumentException($"Index {i} outside manager length {length}", ex); }

Prevention

When it happens

Trigger: Calling Pin(i) on the IMemoryOwner/Memory<T> obtained from UnmanagedMemoryManager with i < 0 or i >= the element count passed at construction (e.g. slicing the Memory incorrectly or passing a length in bytes instead of element count).

Common situations: Confusing byte length with element count (T may be larger than 1 byte); slicing a Memory<T> and pinning with an absolute offset instead of slice-relative; off-by-one loops over elements.

Related errors


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

Appendix: source

Thrown at cs/src/core/VarLen/UnmanagedMemoryManager.cs:68

        /// <param name="length"></param>
        public void SetDestination(T* pointer, int length)
        {
            _pointer = pointer;
            _length = length;
        }

        /// <summary>
        /// Obtains a span that represents the region
        /// </summary>
        public override Span<T> GetSpan() => new Span<T>(_pointer, _length);

        /// <summary>
        /// Provides access to a pointer that represents the data (note: no actual pin occurs)
        /// </summary>
        public override MemoryHandle Pin(int elementIndex = 0)
        {
            if (elementIndex < 0 || elementIndex >= _length)
                throw new ArgumentOutOfRangeException(nameof(elementIndex));
            return new MemoryHandle(_pointer + elementIndex);
        }
        /// <summary>
        /// Has no effect
        /// </summary>
        public override void Unpin() { }

        /// <summary>
        /// Releases all resources associated with this object
        /// </summary>
        protected override void Dispose(bool disposing) { }
    }
}

View on GitHub (pinned to 321d872eab)