microsoft/garnet · error · ArgumentOutOfRangeException
start
Error message
start
What it means
OverflowByteArray wraps a backing byte[] with StartOffset and EndOffset, exposing only the region between them as the logical 'value'. AsReadOnlySpan(int start) returns the remainder of that valid region beginning at start; it throws ArgumentOutOfRangeException(nameof(start)) when start is strictly greater than Length (the valid region size). This guards native-pointer slice creation against out-of-range starts.
Source
Thrown at libs/storage/Tsavorite/cs/src/core/Allocator/OverflowByteArray.cs:51
/// <summary>The total heap size of the array (includes space for offset values and .net array overhead)</summary>
public readonly int HeapMemorySize => Array is null ? 0 : Array.Length + MemoryUtils.ByteArrayOverhead;
readonly int EndOffset => Unsafe.As<byte, OverflowHeader>(ref Array[0]).endOffset;
internal readonly int Length => Array.Length - StartOffset - EndOffset;
/// <inheritdoc/>
public override string ToString() => $"Len {Length}, IsEmpty {IsEmpty}, sOffset {StartOffset}, eOffset {EndOffset}, HeapMemSize {HeapMemorySize}, TotSize {TotalSize}";
/// <summary>ReadOnlySpan of data between offsets</summary>
internal readonly ReadOnlySpan<byte> ReadOnlySpan => Array.AsSpan(StartOffset, Length);
/// <summary>ReadOnlySpan of data between offsets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ReadOnlySpan<byte> AsReadOnlySpan(int start)
{
var length = Length;
return start <= length ? Array.AsSpan(StartOffset + start, length - start) : throw new ArgumentOutOfRangeException(nameof(start));
}
/// <summary>ReadOnlySpan of data between offsets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ReadOnlySpan<byte> AsReadOnlySpan(int start, int len)
{
var length = Length;
return ((ulong)(uint)start + (uint)len <= (uint)length) ? Array.AsSpan(StartOffset + start, len) : throw new ArgumentOutOfRangeException($"start {nameof(start)} + len {len} exceeds length {length}");
}
/// <summary>Span of data between offsets</summary>
internal readonly Span<byte> Span => Array.AsSpan(StartOffset, Length);
/// <summary>Span of data between offsets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Span<byte> AsSpan(int start)
{
var length = Length;
return start <= length ? Array.AsSpan(StartOffset + start, length - start) : throw new ArgumentOutOfRangeException(nameof(start));
}View on GitHub (pinned to 951b0fc683)
Solutions
- Validate start against oba.Length before slicing.
- Derive offsets from the record's own header fields (ActualSize, StartOffset) rather than external math.
- Confirm the record was not truncated (check ActualSize and filler length) before slicing its overflow bytes.
- Add a debug assertion logging start/Length so bad offsets surface early.
Example fix
// before
var span = overflow.AsReadOnlySpan(offset);
// after
if ((uint)offset > (uint)overflow.Length)
throw new InvalidOperationException($"bad offset {offset} > {overflow.Length}");
var span = overflow.AsReadOnlySpan(offset); Defensive patterns
Strategy: validation
Validate before calling
if ((uint)start > (uint)overflow.Length)
throw new InvalidOperationException($"start {start} > Length {overflow.Length}");
var span = overflow.AsReadOnlySpan(start); Prevention
- Always derive offsets from the record's own header fields, not external arithmetic.
- Assert start/Length relationships in debug builds.
- Treat an out-of-range slice as a data-corruption signal, not a transient error.
When it happens
Trigger: Calling AsReadOnlySpan(start) with start > Length — typically from miscomputed offsets when parsing a record's value region, reading a partially-overwritten or truncated overflow record, or off-by-one arithmetic against the record header.
Common situations: Forgetting StartOffset / OverflowHeader.Size when computing an offset; slicing past a value that was shrunk (filler truncation); corrupted or short reads from device; generic span-slicing code that ignores the array's logical bounds.
Related errors
- start {nameof(start)} + len {len} exceeds length {length}
- MutablePercent must be between 10 and 95
- Store Log Memory size or PageCount must be specified
- Index size {IndexMemorySize} should not be less than index m
- Read Cache Log Memory size or PageCount must be specified
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/f02e6204aecdd5d9.
Report an issue: GitHub.