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
- 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).
- Inspect the actual device sector size (logDevice.SectorSize) before constructing the store and pick PageSizeBits accordingly.
- 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
- Always derive PageSizeBits from the device's actual SectorSize, not a hard-coded constant.
- Log device.SectorSize at startup to catch mismatches early.
- Prefer the default PageSizeBits (25) unless you have measured memory pressure.
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
- Allocator with sector size {sectorSize} cannot flush to devi
- LogSettings.LogDevice needs to be specified (e.g., use Devic
- {nameof(logSettings.PageCount)} or {nameof(logSettings.Memor
- {nameof(logSettings.PageSizeBits)} must be between {LogSetti
- {nameof(logSettings.PageSizeBits)} must be >= PageHeader.Siz
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/c35598cd48b36c50.
Report an issue: GitHub.