dotnet/orleans · error · ArgumentException

Invalid offset length

Error message

Invalid offset length

What it means

Thrown by OrleansRelationalDownloadStream.ValidateReadParameters when checked(offset + count) exceeds buffer.Length. The Read/ReadAsync methods guard their buffer slice before touching the DbDataReader; the message 'Invalid offset length' is an ArgumentException signalling a caller-side arithmetic mistake, not a database problem.

Source

Thrown at src/AdoNet/Shared/Storage/OrleansRelationalDownloadStream.cs:211

            base.Dispose(disposing);
        }

        /// <summary>
        /// Checks the parameters passed into a ReadAsync() or Read() are valid.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        private static void ValidateReadParameters(byte[] buffer, long offset, long count)
        {
            ArgumentNullException.ThrowIfNull(buffer);
            ArgumentOutOfRangeException.ThrowIfNegative(offset);
            ArgumentOutOfRangeException.ThrowIfNegative(count);

            if (checked(offset + count) > buffer.Length)
            {
                throw new ArgumentException("Invalid offset length");
            }
        }
    }
}

#nullable restore

View on GitHub (pinned to fca799fa70)

Solutions

  1. Compute count from the remaining space: count = Math.Min(requested, buffer.Length - offset).
  2. Ensure offset and count are both non-negative and that offset + count <= buffer.Length before calling Read.
  3. When offset is 0, pass count = buffer.Length; when using an offset, reduce count accordingly.
  4. Add a debug assert on the invariant offset + count <= buffer.Length in your read loop.

Example fix

// before
stream.Read(buffer, offset: 100, count: buffer.Length); // 100 + Length > Length -> throws

// after
int count = Math.Min(buffer.Length - offset, desired);
stream.Read(buffer, offset, count);
Defensive patterns

Strategy: validation

Validate before calling

static void AssertReadArgs(byte[] buffer, long offset, long count)
{
    if (offset < 0 || count < 0 || checked(offset + count) > buffer.Length)
        throw new ArgumentException("Invalid read args");
}
// call before stream.Read/ReadAsync

Try / catch

try { stream.Read(buf, off, cnt); }
catch (ArgumentException ex) when (ex.Message == "Invalid offset length") { /* recompute off/cnt */ }

Prevention

When it happens

Trigger: Calling Read(buffer, offset, count) or ReadAsync where offset+count > buffer.Length, e.g. a negative offset, an oversized count, or a reused buffer that shrank. Also when a caller passes the full buffer length as count while also using a non-zero offset.

Common situations: Loop-and-offset read patterns that miscalculate remaining space; passing buffer.Length instead of (buffer.Length - offset); buffer pooling where a smaller buffer is returned than the loop expects.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/a33ee055b59f1351. Report an issue: GitHub.