You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
RecoverFromPage throws NullReferenceException on non-inline keys, preventing checkpoint recovery #2164
Garnet accepts and successfully checkpoints a non-inline key, but cannot recover that checkpoint. Restart fails with a NullReferenceException from LogRecord.get_KeyBytes() in RecoverFromPage, and the server exits without listening.
This reproduces with ordinary SET and HSET, with or without --storage-tier. It does not require cluster mode, custom modules, concurrent requests, or injected corruption. All writes and both SAVE commands return success before restart.
The failed server also exits with code 0 after logging Unable to initialize server due to exception, which may hide the startup failure from a service manager.
Steps to reproduce the bug
The script uses fresh containers, preserves the server's writable layer across docker restart, and cleans up everything it creates.
OK
OK
1
OK
status=exited exitCode=0
Error during recovery of store; storeVersion = 0;
System.NullReferenceException: Object reference not set to an instance of an object.
at Tsavorite.core.LogRecord.get_KeyBytes() in .../Allocator/LogRecord.cs:line 1033
at Tsavorite.core.TsavoriteKV`2.RecoverFromPage(...) in .../Recovery/Recovery.cs:line 1310
at Tsavorite.core.TsavoriteKV`2.ProcessReadSnapshotPage(...) in .../Recovery/Recovery.cs:line 1221
at Tsavorite.core.TsavoriteKV`2.RecoverSnapshotPages(...) in .../Recovery/Recovery.cs:line 1142
at Tsavorite.core.TsavoriteKV`2.RecoverHybridLogFromSnapshotFileAsync(...) in .../Recovery/Recovery.cs:line 983
Unable to initialize server due to exception: Object reference not set to an instance of an object.
Additional isolated cells:
Version
Command
Key bytes
Storage tier
Restart result
2.1.8
HSET
16
enabled
Server runs; HGET returns value
2.1.8
HSET
1,024
enabled
Same recovery exception
2.1.8
HSET
65,536
enabled
Same recovery exception
2.1.8
SET
1,024
enabled
Same recovery exception
2.1.8
HSET
1,024
disabled
Same recovery exception
2.1.7
HSET
1,024
enabled
Same recovery exception
The exact key-length boundary was not measured.
Expected behavior
The key and value survive checkpoint recovery and are readable after restart. If recovery prevents startup, the server process exits with a nonzero status.
Release version
2.1.8 (ghcr.io/microsoft/garnet@sha256:20d9f41b02bcdf8aae1ad734fb7e31ef98b06efffdfa487eeea49687bdd3ff55); also reproduced on 2.1.7.
OS version
Docker Desktop 29.7.2, Linux arm64 containers.
Additional context
The failure appears to come from using an address-only LogRecord while rebuilding the hash index. RecoverFromPage constructs new LogRecord(pageStartPhysicalAddress + recordOffset) and then calls storeFunctions.GetKeyHashCode64(logRecord). The address-only constructor explicitly says it must not be used when an overflow allocator is needed. It leaves objectIdMap unset, while the non-inline key getter dereferences objectIdMap.GetOverflowByteArray(...).
This explains the stack and the short-key/long-key contrast. Recovery needs the page's object map when hashing a non-inline key; skipping the record would lose data. The same address-only construction is present on main at c323bbf7aa2783c1e9981edd387437d2618ff750 (source inspection only; that revision was not executed).
Activity
[Tsavorite] Fix IndexOutOfRangeException disposing a record with an u…