microsoft/garnet · error · ArgumentOutOfRangeException
start {nameof(start)} + len {len} exceeds length {length}
Error message
start {nameof(start)} + len {len} exceeds length {length} What it means
AsReadOnlySpan(int start, int len) returns len bytes of the valid region beginning at start. It uses an overflow-safe check — (uint)start + (uint)len <= (uint)length — and throws ArgumentOutOfRangeException when the requested window runs past Length. This is the two-argument bounds guard for native-pointer slice creation.
Source
Thrown at libs/storage/Tsavorite/cs/src/core/Allocator/OverflowByteArray.cs:58
/// <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));
}
/// <summary>ReadOnlySpan of data between offsets</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Span<byte> AsSpan(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}");
}View on GitHub (pinned to 951b0fc683)
Solutions
- Clamp/validate that (ulong)(uint)start + (ulong)(uint)len <= (ulong)(uint)oba.Length before calling.
- Verify the source record's ActualSize/filler length matches the len you intend to read.
- Use the record's RecordFieldInfo to obtain authoritative field lengths instead of recomputing.
- Treat any negative start/len as a programmer error and reject before the call.
Example fix
// before
var span = overflow.AsReadOnlySpan(offset, len);
// after
if ((ulong)(uint)offset + (ulong)(uint)len > (ulong)(uint)overflow.Length)
throw new InvalidOperationException($"window {offset}+{len} > {overflow.Length}");
var span = overflow.AsReadOnlySpan(offset, len); Defensive patterns
Strategy: validation
Validate before calling
if ((ulong)(uint)start + (ulong)(uint)len > (ulong)(uint)overflow.Length)
throw new InvalidOperationException($"window {start}+{len} > Length {overflow.Length}");
var span = overflow.AsReadOnlySpan(start, len); Prevention
- Use the overflow-safe (uint)+(uint) check rather than int arithmetic to catch negative inputs.
- Cross-check len against the record's declared field length before slicing.
- Reject negative start/len at the call site.
When it happens
Trigger: Calling AsReadOnlySpan(start, len) where start+len exceeds Length, including the integer-overflow case where a negative start or len would otherwise wrap past the end. Triggered by reading more value bytes than the record stores, or miscomputing len from header fields.
Common situations: Reading a value field of declared length N from an overflow region shorter than N (corrupt/truncated record); copying a fixed-size header that the shrunken record no longer fully contains; arithmetic that adds StartOffset twice.
Related errors
- start
- 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/62ff8c974db0d4b4.
Report an issue: GitHub.