microsoft/garnet · critical · TsavoriteException

Page size must be at least of device sector size ({sectorSiz

Error message

Page size must be at least of device sector size ({sectorSize} bytes). Set PageSizeBits accordingly.

What it means

Thrown during allocator initialization when the configured page size (PageSize, derived from PageSizeBits) is smaller than the storage device's reported sector size. Tsavorite aligns page flushes to the device sector boundary, so a page that cannot hold even one sector is unusable. The check guards AlignedPageSizeBytes = RoundUp(PageSize, sectorSize), which would otherwise round a sub-sector page up to a meaningless size.

Source

Thrown at libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs:653

            // Segment size
            LogSegmentSizeBits = logSettings.SegmentSizeBits;
            SegmentSize = 1L << LogSegmentSizeBits;
            if (SegmentSize < PageSize)
                throw new TsavoriteException($"Segment ({SegmentSize}) must be at least of page size ({PageSize})");

            PageStatusIndicator = new FullPageStatus[BufferSize];

            if (!IsNullDevice)
            {
                PendingFlush = new PendingFlushList[BufferSize];
                for (int i = 0; i < BufferSize; i++)
                    PendingFlush[i] = new PendingFlushList();
            }
            device = logSettings.LogDevice;
            sectorSize = (int)device.SectorSize;

            if (PageSize < sectorSize)
                throw new TsavoriteException($"Page size must be at least of device sector size ({sectorSize} bytes). Set PageSizeBits accordingly.");

            AlignedPageSizeBytes = RoundUp(PageSize, sectorSize);

            if (BufferSize > 0)
            {
                pageArrays = new byte[BufferSize][];
                pagePointersArray = GC.AllocateArray<long>(BufferSize, pinned: true);
                pagePointers = (long*)Unsafe.AsPointer(ref pagePointersArray[0]);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal long GetPhysicalAddress(long logicalAddress)
        {
            // if (disposed)    // TODO: Clean up dispose sequence
            //     ThrowTsavoriteException("GetPhysicalAddress called when disposed");

            // Index of page within the circular buffer, and offset on the page.

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Raise LogSettings.PageSizeBits so that (1 << PageSizeBits) >= device.SectorSize (e.g. use the default 25, or at least 12 for 4KB sectors, 13+ for safety).
  2. Inspect the actual device sector size (logDevice.SectorSize) before constructing the store and pick PageSizeBits accordingly.
  3. If using a custom IDevice, verify its SectorSize reflects the real hardware and is not accidentally inflated.

Example fix

// before
var logSettings = new LogSettings { PageSizeBits = 12, LogDevice = device };
// after (device.SectorSize is 4096, so 1<<12==4096 only matches exactly; give headroom)
var sectorBits = (int)Math.Ceiling(Math.Log2(device.SectorSize));
var logSettings = new LogSettings { PageSizeBits = Math.Max(sectorBits, 25), LogDevice = device };
Defensive patterns

Strategy: validation

Validate before calling

// Validate before constructing the store
var sectorSize = (int)logDevice.SectorSize;
var pageSize = 1 << logSettings.PageSizeBits;
if (pageSize < sectorSize)
    throw new ArgumentException($"PageSizeBits {logSettings.PageSizeBits} ({pageSize}B) < device sector size {sectorSize}B");

Prevention

When it happens

Trigger: Constructing a TsavoriteKV with LogSettings.PageSizeBits set so low that (1 << PageSizeBits) < logDevice.SectorSize. Hits AllocatorBase.Initialize() at startup. Common with PageSizeBits=12 (4KB) against a 4Kn (4096-byte native) device that reports a larger logical sector, or with a custom IDevice whose SectorSize is overridden to a large value.

Common situations: Copying a config tuned for a 512-byte-sector disk onto a 4K-native (4Kn) advanced-format disk; using an Azure Managed Disk / NVMe device that reports 4096-byte physical sectors; a custom MemoryDevice/NullDevice set with an inflated SectorSize; lowering PageSizeBits to reduce memory footprint without accounting for the underlying device.

Related errors


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