microsoft/FASTER · error · FasterException
Size of key-value exceeds max of 2GB:
Error message
Size of key-value exceeds max of 2GB:
What it means
FASTER's GenericAllocator reads a logical key-value's record(s) from disk as one contiguous read into a single buffer, and that read length is stored in an int. When the total byte span of a record (endAddress - startAddress) exceeds int.MaxValue (2GB), it cannot be read/allocated in one piece, so GenericAllocator throws FasterException during an async read (AsyncGetAtAddress path).
Solutions
- Reduce the size of individual key-values below 2GB by splitting large values into chunks stored under multiple keys (e.g. key_0..key_n)
- Use a smaller serializer output: compress the payload before storing, or switch to a blittable/ref struct type with a smaller fixed footprint
- If large objects are inherent, store the blob in external storage (file/object store) and keep only a reference/handle in FASTER
- Re-check record overhead: the 2GB limit includes the record header and multiple contiguous records spanned during a read; shrink both value size and record packing
Example fix
// before
faster.Upsert(key, hugeByteArray); // > 2GB value
// after
const int ChunkSize = 512 * 1024 * 1024;
for (int i = 0; i * ChunkSize < hugeByteArray.Length; i++)
{
var chunk = new byte[Math.Min(ChunkSize, hugeByteArray.Length - i * ChunkSize)];
Array.Copy(hugeByteArray, i * ChunkSize, chunk, 0, chunk.Length);
faster.Upsert(new Key(key, i), chunk);
} Defensive patterns
Strategy: validation
Validate before calling
// Estimate serialized record size before upserting
long approxSize = keySize + valueSize + RecordHeaderSize; // e.g. 4-8 bytes header
if (approxSize > int.MaxValue)
throw new InvalidOperationException($"Value of {valueSize} bytes exceeds FASTER's 2GB per-record limit; chunk the value."); Try / catch
try
{
faster.Upsert(key, largeValue);
}
catch (FasterException ex) when (ex.Message.StartsWith("Size of key-value exceeds max of 2GB"))
{
// fall back to chunked storage or external blob store
} Prevention
- Chunk any value larger than ~1GB before storing in FASTER
- Store very large blobs in external storage and keep handles in FASTER
- Account for record headers when computing value size limits
- Use 64-bit length checks (long) when measuring serialized sizes, not int
When it happens
Trigger: Calling Read/ReadAsync (or an operation that pulls a record from disk, e.g. a cache miss during an upsert/read-copy path) when a single serialized key+value spans more than 2GB of contiguous log address space; also hit when scanning adjacent records coalesce into a >2GB span (startAddress of the first record to endAddress of the last).
Common situations: Storing multi-GB blobs/objects as single FASTER values with generic allocator backing devices (local storage device); users migrating from a heap-based store to disk where record size limits were previously implicit; accidentally writing huge arrays as one value instead of chunking.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- Allocator with sector size
- Incremental snapshots not supported with generic allocator
- Physical pointer returned by allocator: de-reference…
- Physical pointer returned by allocator: de-reference…
- Out of order message within session
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/06c06f7670002220.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/Allocator/GenericAllocator.cs:1015
long endAddress = -1;
if (KeyHasObjects())
{
var x = GetKeyAddressInfo((long)record);
startAddress = x->Address;
endAddress = x->Address + x->Size;
}
if (ValueHasObjects() && !GetInfoFromBytePointer(record).Tombstone)
{
var x = GetValueAddressInfo((long)record);
if (startAddress == -1)
startAddress = x->Address;
endAddress = x->Address + x->Size;
}
// We are limited to a 2GB size per key-value
if (endAddress-startAddress > int.MaxValue)
throw new FasterException("Size of key-value exceeds max of 2GB: " + (endAddress - startAddress));
if (startAddress < 0)
startAddress = 0;
AsyncGetFromDisk(startAddress, (int)(endAddress - startAddress), ctx, ctx.record);
return false;
}
// Parse the key and value objects
MemoryStream ms = new MemoryStream(ctx.objBuffer.buffer);
ms.Seek(ctx.objBuffer.offset + ctx.objBuffer.valid_offset, SeekOrigin.Begin);
if (KeyHasObjects())
{
var keySerializer = SerializerSettings.keySerializer();
keySerializer.BeginDeserialize(ms);
keySerializer.Deserialize(out ctx.key);
keySerializer.EndDeserialize();View on GitHub (pinned to 321d872eab)