{"record":{"id":"a33ee055b59f1351","repo":"dotnet/orleans","slug":"invalid-offset-length","errorCode":null,"errorMessage":"Invalid offset length","messagePattern":"Invalid offset length","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/AdoNet/Shared/Storage/OrleansRelationalDownloadStream.cs","lineNumber":211,"sourceCode":"\n            base.Dispose(disposing);\n        }\n\n        /// <summary>\n        /// Checks the parameters passed into a ReadAsync() or Read() are valid.\n        /// </summary>\n        /// <param name=\"buffer\"></param>\n        /// <param name=\"offset\"></param>\n        /// <param name=\"count\"></param>\n        private static void ValidateReadParameters(byte[] buffer, long offset, long count)\n        {\n            ArgumentNullException.ThrowIfNull(buffer);\n            ArgumentOutOfRangeException.ThrowIfNegative(offset);\n            ArgumentOutOfRangeException.ThrowIfNegative(count);\n\n            if (checked(offset + count) > buffer.Length)\n            {\n                throw new ArgumentException(\"Invalid offset length\");\n            }\n        }\n    }\n}\n\n#nullable restore\n","sourceCodeStart":193,"sourceCodeEnd":218,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/AdoNet/Shared/Storage/OrleansRelationalDownloadStream.cs#L193-L218","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Compute count from the remaining space: count = Math.Min(requested, buffer.Length - offset).","Ensure offset and count are both non-negative and that offset + count <= buffer.Length before calling Read.","When offset is 0, pass count = buffer.Length; when using an offset, reduce count accordingly.","Add a debug assert on the invariant offset + count <= buffer.Length in your read loop."],"exampleFix":"// before\nstream.Read(buffer, offset: 100, count: buffer.Length); // 100 + Length > Length -> throws\n\n// after\nint count = Math.Min(buffer.Length - offset, desired);\nstream.Read(buffer, offset, count);","handlingStrategy":"validation","validationCode":"static void AssertReadArgs(byte[] buffer, long offset, long count)\n{\n    if (offset < 0 || count < 0 || checked(offset + count) > buffer.Length)\n        throw new ArgumentException(\"Invalid read args\");\n}\n// call before stream.Read/ReadAsync","typeGuard":null,"tryCatchPattern":"try { stream.Read(buf, off, cnt); }\ncatch (ArgumentException ex) when (ex.Message == \"Invalid offset length\") { /* recompute off/cnt */ }","preventionTips":["Compute count as Math.Min(requested, buffer.Length - offset).","Keep offset 0 when reading into a fresh buffer.","Add a debug assert offset + count <= buffer.Length."],"tags":["csharp","dotnet","orleans","adonet","stream","argument-validation"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}