microsoft/FASTER · critical · FasterException

Allocator with sector size

Error message

Allocator with sector size {sectorSize} cannot flush to device with sector size {device.SectorSize}

What it means

AllocatorBase.VerifyCompatibleSectorSize enforces that the allocator's sector size is an integer multiple of the flush device's sector size (allocatorSectorSize % deviceSectorSize == 0). FASTER aligns flushes to sector boundaries; flushing to a device with larger sectors than the allocator assumed would produce misaligned writes or data corruption, so it throws FasterException.

Solutions

  1. Configure the log's sector size to be a multiple of the device's sector size (e.g. pass sectorSize: 4096 when the device reports 4096).
  2. Recreate the device with matching/explicit sector size parameters so allocator and device agree.
  3. Move the log onto a device whose sector size divides the allocator's sector size (e.g. use a file/device emulation with 512-byte sectors).

Example fix

// before
var device = Devices.CreateLogDevice(path, sectorSize: 512); // device reports 4096
// after
var device = Devices.CreateLogDevice(path, sectorSize: 4096); // matches allocator sector size
Defensive patterns

Strategy: validation

Validate before calling

if (allocatorSectorSize % device.SectorSize != 0)
    throw new InvalidOperationException($"Set log sector size to a multiple of device sector size {device.SectorSize}");

Try / catch

try { store = new FasterKV<K,V>(...); } catch (FasterException) { /* recreate devices with sectorSize = device.SectorSize */ }

Prevention

When it happens

Trigger: Creating a hybrid log/device stack where the log's configured sector size (or a device's reported sector size) is smaller-grained than the target device — e.g. allocator sectorSize=512 while device.SectorSize=4096, attaching devices created with different sector settings, or a device emulation layer reporting a large sector size.

Common situations: Running on storage (or device emulation like local emulated devices) that reports 4K-native sectors while FASTER was configured with 512-byte sectors; moving checkpoints/logs between devices with different sector sizes; Windows/Linux differences in reported sector geometry.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

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

        /// <summary>
        /// Write async to device
        /// </summary>
        /// <typeparam name="TContext"></typeparam>
        /// <param name="startPage"></param>
        /// <param name="flushPage"></param>
        /// <param name="pageSize"></param>
        /// <param name="callback"></param>
        /// <param name="result"></param>
        /// <param name="device"></param>
        /// <param name="objectLogDevice"></param>
        /// <param name="localSegmentOffsets"></param>
        /// <param name="fuzzyStartLogicalAddress">Start address of fuzzy region, which contains old and new version records (we use this to selectively flush only old-version records during snapshot checkpoint)</param>
        protected abstract void WriteAsyncToDevice<TContext>(long startPage, long flushPage, int pageSize, DeviceIOCompletionCallback callback, PageAsyncFlushResult<TContext> result, IDevice device, IDevice objectLogDevice, long[] localSegmentOffsets, long fuzzyStartLogicalAddress);

        private protected void VerifyCompatibleSectorSize(IDevice device)
        {
            if (this.sectorSize % device.SectorSize != 0)
                throw new FasterException($"Allocator with sector size {sectorSize} cannot flush to device with sector size {device.SectorSize}");
        }

        internal long GetReadOnlyLagAddress() => ReadOnlyLagAddress;

        /// <summary>
        /// Delta flush
        /// </summary>
        /// <param name="startAddress"></param>
        /// <param name="endAddress"></param>
        /// <param name="prevEndAddress"></param>
        /// <param name="version"></param>
        /// <param name="deltaLog"></param>
        /// <param name="completedSemaphore"></param>
        /// <param name="throttleCheckpointFlushDelayMs"></param>
        internal unsafe virtual void AsyncFlushDeltaToDevice(long startAddress, long endAddress, long prevEndAddress, long version, DeltaLog deltaLog, out SemaphoreSlim completedSemaphore, int throttleCheckpointFlushDelayMs)
        {
            logger?.LogTrace("Starting async delta log flush with throttling {throttlingEnabled}", throttleCheckpointFlushDelayMs >= 0 ? $"enabled ({throttleCheckpointFlushDelayMs}ms)" : "disabled");

View on GitHub (pinned to 321d872eab)