microsoft/garnet · error · TsavoriteException

Iterator address is less than log HeadAddress in memory-scan

Error message

Iterator address is less than log HeadAddress in memory-scan mode

What it means

SpanByteScanIterator.LoadPageIfNeeded throws when frameSize == 0 (no read-back frame / no buffered disk pages), currentAddress < hlogBase.HeadAddress (the address has been evicted or overwritten in memory), and assumeInMemory is false. Pure memory-scan mode cannot serve records that have already rolled off the in-memory log.

Source

Thrown at libs/storage/Tsavorite/cs/src/core/Allocator/SpanByteScanIterator.cs:142

                return false;
            }

            // Success; caller will suspend the epoch as needed.
            return true;
        }

        private bool LoadPageIfNeeded(out long headAddress, out long currentPage, long stopAddress)
        {
            headAddress = hlogBase.HeadAddress;

            if (currentAddress < hlogBase.BeginAddress && !assumeInMemory)
                currentAddress = hlogBase.BeginAddress;

            // If currentAddress < headAddress and we're not buffering and not guaranteeing the records are in memory, fail.
            if (frameSize == 0 && currentAddress < headAddress && !assumeInMemory)
            {
                // Caller will suspend the epoch.
                throw new TsavoriteException("Iterator address is less than log HeadAddress in memory-scan mode");
            }

            currentPage = hlogBase.GetPage(currentAddress);
            if (currentAddress < headAddress && !assumeInMemory)
                _ = BufferAndLoad(currentAddress, currentPage, currentPage % frameSize, headAddress, stopAddress);

            // Success; keep the epoch held for GetNext (SnapCursorToLogicalAddress will Suspend()).
            return true;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal long SnapToLogicalAddressBoundary(ref long logicalAddress, long headAddress, long currentPage)
        {
            var offset = hlogBase.GetOffsetOnPage(logicalAddress);

            // Subtracting offset means this physicalAddress is at the start of the page. Adjust for PageHeader.
            long totalSizes = PageHeader.Size;
            if (currentPage == 0)

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Increase the log MemorySize so the entire scanned address range stays resident in memory.
  2. Start the scan at or after the current HeadAddress (use hlog.HeadAddress / BeginAddress), not a saved stale address.
  3. Use a disk-backed scan (ensure the read frame is allocated so frameSize > 0) so evicted pages are read back.
  4. If skipping evicted records is acceptable, document it and start the iterator at HeadAddress.

Example fix

// before
using var it = store.Log.Scan(startAddress: staleAddr, ...);

// after: clamp the start address to the in-memory head
long begin = Math.Max(staleAddr, store.Log.HeadAddress);
using var it = store.Log.Scan(startAddress: begin, ...);
Defensive patterns

Strategy: validation

Validate before calling

long begin = Math.Max(requestedStartAddress, store.Log.HeadAddress);
if (!assumeInMemory && requestedStartAddress < store.Log.HeadAddress && frameSize == 0)
    throw new InvalidOperationException($"start {requestedStartAddress} < HeadAddress {store.Log.HeadAddress}; raise MemorySize or use a disk-backed scan");
using var it = store.Log.Scan(begin, ...);

Prevention

When it happens

Trigger: Starting or continuing a memory-only scan (no disk read frame) at an address behind HeadAddress — the log has wrapped and overwritten/evicted those records — without setting assumeInMemory and without a buffered frame to read them back from disk.

Common situations: Long-running scan that falls behind while the log rolls over; resuming a scan from a saved stale address; MemorySize configured too small for the scan range; using the in-memory scan API for data that has spilled to disk.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/466508f0f4604bbe. Report an issue: GitHub.