microsoft/FASTER · error · FasterException

Page size must be at least of device sector size

Error message

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

What it means

FASTER aligns pages to the underlying device's sector size so I/O is done on sector boundaries. Each page (1 << PageSizeBits) must be at least as large as the log device's reported SectorSize; otherwise reads/writes cannot be aligned correctly. The allocator queries device.SectorSize at construction and throws if PageSize is smaller.

Solutions

  1. Increase LogSettings.PageSizeBits so PageSize >= device.SectorSize (e.g. at least 12 bits for 4KB sectors).
  2. Check the actual sector size of your device (device.SectorSize) before choosing PageSizeBits.
  3. Use a device whose sector size matches your page configuration (e.g. a local emulation device with 512-byte sectors for small-page tests).

Example fix

// before
var settings = new LogSettings {
  LogDevice = new AzureStorageDevice("..."), // 4096-byte sectors
  PageSizeBits = 9 // 512B < 4096B sector size
};

// after
var settings = new LogSettings {
  LogDevice = new AzureStorageDevice("..."),
  PageSizeBits = 12 // 4KB >= sector size
};
Defensive patterns

Strategy: validation

Validate before calling

if ((1 << settings.PageSizeBits) < settings.LogDevice.SectorSize)
    throw new ArgumentException($"PageSize ({1 << settings.PageSizeBits}) must be >= device sector size ({settings.LogDevice.SectorSize})");

Type guard

bool PageMeetsSector(LogSettings s) => s.LogDevice != null && (1L << s.PageSizeBits) >= s.LogDevice.SectorSize;

Try / catch

try { var fht = new FasterKV<K, V>(size, settings); }
catch (FasterException ex) when (ex.Message.Contains("device sector size")) { /* increase PageSizeBits */ }

Prevention

When it happens

Trigger: Using a device with a large sector size (e.g. 4096-byte AzureStorageDevice or certain SSDs) while LogSettings.PageSizeBits is too small, e.g. PageSizeBits=8 (256 bytes) against a 4KB-sector device.

Common situations: Cloud-storage devices (Azure blob) report 4KB sectors while users configure small pages for unit tests; compressed/QCOW or network devices reporting non-512 sector sizes.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at cs/src/core/Allocator/AllocatorBase.cs:1028

            if (SegmentSize < PageSize)
                throw new FasterException($"Segment ({SegmentSize}) must be at least of page size ({PageSize})");

            if ((LogTotalSizeBits != 0) && (LogTotalSizeBytes < PageSize))
                throw new FasterException($"Memory size ({LogTotalSizeBytes}) must be configured to be either 1 (i.e., 0 bits) or at least 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 = settings.LogDevice;
            sectorSize = (int)device.SectorSize;

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

            AlignedPageSizeBytes = (PageSize + (sectorSize - 1)) & ~(sectorSize - 1);
        }

        /// <summary>
        /// Number of extra overflow pages allocated
        /// </summary>
        internal abstract int OverflowPageCount { get; }


        /// <summary>
        /// Reset the hybrid log. WARNING: assumes that threads have drained out at this point.
        /// </summary>
        public virtual void Reset()
        {
            var newBeginAddress = GetTailAddress();

            // Shift read-only addresses to tail without flushing

View on GitHub (pinned to 321d872eab)