microsoft/garnet · error · TsavoriteException

TsavoriteLogAllocator does not support VerifyRecordFromDiskC

Error message

TsavoriteLogAllocator does not support VerifyRecordFromDiskCallback

What it means

VerifyRecordFromDiskCallback is a KV-store allocator hook called during disk read to validate record chaining (previous-address links, record lengths) as pages are loaded from disk. TsavoriteLogAllocator uses a different on-disk format and recovery path that does not use per-record verification chaining, so it throws a TsavoriteException to signal the unsupported code path.

Source

Thrown at libs/storage/Tsavorite/cs/src/core/Allocator/TsavoriteLogAllocatorImpl.cs:122

        /// <inheritdoc/>
        protected override void WriteAsyncToDeviceForSnapshot<TContext>(long startPage, long flushPage, int pageSize, DeviceIOCompletionCallback callback,
            PageAsyncFlushResult<TContext> asyncResult, IDevice device, IDevice objectLogDevice, long fuzzyStartLogicalAddress)
        {
            VerifyCompatibleSectorSize(device);
            var alignedPageSize = (pageSize + (sectorSize - 1)) & ~(sectorSize - 1);

            WriteInlinePageAsync((IntPtr)pagePointers[flushPage % BufferSize],
                        (ulong)(AlignedPageSizeBytes * (flushPage - startPage)),
                        (uint)alignedPageSize, callback, asyncResult,
                        device);
        }

        protected override void ReadAsync<TContext>(ulong alignedSourceAddress, IntPtr destinationPtr, uint aligned_read_length,
                DeviceIOCompletionCallback callback, PageAsyncReadResult<TContext> asyncResult, IDevice device)
            => device.ReadAsync(alignedSourceAddress, destinationPtr, aligned_read_length, callback, asyncResult);

        private protected override bool VerifyRecordFromDiskCallback(ref AsyncIOContext ctx, out long prevAddressToRead, out int prevLengthToRead)
            => throw new TsavoriteException("TsavoriteLogAllocator does not support VerifyRecordFromDiskCallback");

        /// <summary>
        /// Iterator interface for pull-scanning Tsavorite log
        /// </summary>
        public override ITsavoriteScanIterator Scan(TsavoriteKV<TsavoriteLogStoreFunctions, TsavoriteLogAllocator> store,
                long beginAddress, long endAddress, DiskScanBufferingMode diskScanBufferingMode, bool includeSealedRecords)
            => throw new TsavoriteException("TsavoriteLogAllocator Scan methods should not be used");

        /// <summary>
        /// Implementation for push-scanning Tsavorite log, called from LogAccessor
        /// </summary>
        internal override bool Scan<TScanFunctions>(TsavoriteKV<TsavoriteLogStoreFunctions, TsavoriteLogAllocator> store,
                long beginAddress, long endAddress, ref TScanFunctions scanFunctions, DiskScanBufferingMode diskScanBufferingMode)
            => throw new TsavoriteException("TsavoriteLogAllocator Scan methods should not be used");

        /// <summary>
        /// Implementation for push-scanning Tsavorite log with a cursor, called from LogAccessor
        /// </summary>

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Ensure disk-verification callbacks only run for KV store allocators, not the log allocator.
  2. Use the log store's native recovery API which handles its own record validation.
  3. Branch the verification path on allocator type before invoking the callback.

Example fix

// before
bool ok = allocator.VerifyRecordFromDiskCallback(ref ctx, out prevAddr, out prevLen);

// after
bool ok = allocator is TsavoriteLogAllocator
    ? true
    : allocator.VerifyRecordFromDiskCallback(ref ctx, out prevAddr, out prevLen);
Defensive patterns

Strategy: type-guard

Validate before calling

if (allocator is TsavoriteLogAllocator) throw new NotSupportedException("VerifyRecordFromDiskCallback is not supported on the log allocator; use its native recovery path.");

Type guard

static bool SupportsVerifyFromDisk(IAllocator a) => a is not TsavoriteLogAllocator;

Try / catch

try { allocator.VerifyRecordFromDiskCallback(ref ctx, out var prev, out var len); }
catch (TsavoriteException) when (allocator is TsavoriteLogAllocator) { /* use log-native recovery */ }

Prevention

When it happens

Trigger: Recovery or checkpoint-restore logic reaching VerifyRecordFromDiskCallback on a TsavoriteLogAllocator; generic disk-read verification code that runs the same callback for all allocator types.

Common situations: Custom checkpoint/recovery implementations; upgrading a KV-store verification routine and accidentally wiring it into the log store's allocator.

Related errors


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