{"record":{"id":"f4efd5c8d0e7b707","repo":"dotnet/reactive","slug":"throw-new-argumentoutofrangeexception-nameof-buffersize","errorCode":null,"errorMessage":"throw new ArgumentOutOfRangeException(nameof(bufferSize));","messagePattern":"throw new ArgumentOutOfRangeException\\(nameof\\(bufferSize\\)\\);","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Replay.cs","lineNumber":288,"sourceCode":"                throw new ArgumentNullException(nameof(source));\n            if (selector == null)\n                throw new ArgumentNullException(nameof(selector));\n            if (window < TimeSpan.Zero)\n                throw new ArgumentOutOfRangeException(nameof(window));\n            if (scheduler == null)\n                throw new ArgumentNullException(nameof(scheduler));\n\n            return Multicast(source, () => new ValueTask<IAsyncSubject<TSource, TSource>>(new SequentialReplayAsyncSubject<TSource>(window, scheduler)), selector);\n        }\n\n        public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, ValueTask<IAsyncObservable<TResult>>> selector, int bufferSize, TimeSpan window)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (selector == null)\n                throw new ArgumentNullException(nameof(selector));\n            if (bufferSize < 0)\n                throw new ArgumentOutOfRangeException(nameof(bufferSize));\n            if (window < TimeSpan.Zero)\n                throw new ArgumentOutOfRangeException(nameof(window));\n\n            return Multicast(source, () => new ValueTask<IAsyncSubject<TSource, TSource>>(new SequentialReplayAsyncSubject<TSource>(bufferSize, window)), selector);\n        }\n\n        public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, ValueTask<IAsyncObservable<TResult>>> selector, int bufferSize, TimeSpan window, IAsyncScheduler scheduler)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (selector == null)\n                throw new ArgumentNullException(nameof(selector));\n            if (bufferSize < 0)\n                throw new ArgumentOutOfRangeException(nameof(bufferSize));\n            if (window < TimeSpan.Zero)\n                throw new ArgumentOutOfRangeException(nameof(window));\n            if (scheduler == null)\n                throw new ArgumentNullException(nameof(scheduler));","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Replay.cs#L270-L306","documentation":"The Replay(source, selector, bufferSize, window) operator validates bufferSize before creating a SequentialReplayAsyncSubject. It throws ArgumentOutOfRangeException when bufferSize is negative, because a replay buffer cannot hold a negative number of items. Only negative values are rejected; 0 is allowed (no buffered history, only live notification).","triggerScenarios":"Calling AsyncObservable.Replay(source, selector, bufferSize, window) with a bufferSize parameter that is < 0, e.g. a computed size from an unvalidated config value or a subtraction underflow like newSize - removedItems.","commonSituations":"Reading bufferSize from appsettings/environment variables without validation; computing a buffer size with integer arithmetic that goes negative; copying a call site from another operator and passing an unrelated negative value.","solutions":["Pass a non-negative bufferSize (0 for replay-live-only, int.MaxValue for unlimited history).","Clamp the value before the call: bufferSize = Math.Max(0, computedSize).","Validate configuration inputs at startup so negative sizes never reach the operator."],"exampleFix":"// before\nvar replayed = AsyncObservable.Replay(source, sel, bufferSize: -1, window: TimeSpan.FromSeconds(5));\n// after\nif (bufferSize < 0) bufferSize = 0;\nvar replayed = AsyncObservable.Replay(source, sel, bufferSize, window: TimeSpan.FromSeconds(5));","handlingStrategy":"validation","validationCode":"if (bufferSize < 0) throw new ArgumentException(\"bufferSize must be >= 0\", nameof(bufferSize));","typeGuard":null,"tryCatchPattern":"try { var replayed = AsyncObservable.Replay(source, sel, bufferSize, window); } catch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"bufferSize\") { /* use 0 or int.MaxValue and retry construction */ }","preventionTips":["Never use -1 to mean 'unlimited' with this API; use int.MaxValue.","Validate buffer-size configuration at startup.","Clamp computed sizes with Math.Max(0, size)."],"tags":["argument-validation","argument-out-of-range","reactive-extensions"],"backgroundTag":"argument-out-of-range","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}