{"record":{"id":"8746479073639d3e","repo":"dotnet/reactive","slug":"specified-argument-was-out-of-the-range-of-valid-values-874647","errorCode":null,"errorMessage":"Specified argument was out of the range of valid values. (Parameter 'timeSpan')","messagePattern":"Specified argument was out of the range of valid values\\. \\(Parameter 'timeSpan'\\)","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs","lineNumber":39,"sourceCode":"        /// <param name=\"timeSpan\">Length of each buffer.</param>\n        /// <returns>An observable sequence of buffers.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> is null.</exception>\n        /// <exception cref=\"ArgumentOutOfRangeException\"><paramref name=\"timeSpan\"/> is less than TimeSpan.Zero.</exception>\n        /// <remarks>\n        /// Specifying a TimeSpan.Zero value for <paramref name=\"timeSpan\"/> is not recommended but supported, causing the scheduler to create buffers as fast as it can.\n        /// Because all source sequence elements end up in one of the buffers, some buffers won't have a zero time span. This is a side-effect of the asynchrony introduced\n        /// by the scheduler, where the action to close the current buffer and to create a new buffer may not execute immediately, despite the TimeSpan.Zero due time.\n        /// </remarks>\n        public static IObservable<IList<TSource>> Buffer<TSource>(this IObservable<TSource> source, TimeSpan timeSpan)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (timeSpan < TimeSpan.Zero)\n            {\n                throw new ArgumentOutOfRangeException(nameof(timeSpan));\n            }\n\n            return s_impl.Buffer(source, timeSpan);\n        }\n\n        /// <summary>\n        /// Projects each element of an observable sequence into consecutive non-overlapping buffers which are produced based on timing information, using the specified scheduler to run timers.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence, and in the lists in the result sequence.</typeparam>\n        /// <param name=\"source\">Source sequence to produce buffers over.</param>\n        /// <param name=\"timeSpan\">Length of each buffer.</param>\n        /// <param name=\"scheduler\">Scheduler to run buffering timers on.</param>\n        /// <returns>An observable sequence of buffers.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"scheduler\"/> is null.</exception>\n        /// <exception cref=\"ArgumentOutOfRangeException\"><paramref name=\"timeSpan\"/> is less than TimeSpan.Zero.</exception>\n        /// <remarks>\n        /// Specifying a TimeSpan.Zero value for <paramref name=\"timeSpan\"/> is not recommended but supported, causing the scheduler to create buffers as fast as it can.\n        /// Because all source sequence elements end up in one of the buffers, some buffers won't have a zero time span. This is a side-effect of the asynchrony introduced","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs#L21-L57","documentation":"System.Reactive's public Buffer(source, timeSpan) overload validates its arguments eagerly at the call site before creating the underlying observable. It throws ArgumentOutOfRangeException when timeSpan is negative because a negative buffer window duration has no valid meaning. This fail-fast check surfaces the bug at the caller instead of deep inside the query.","triggerScenarios":"Calling Observable.Buffer(source, TimeSpan.Zero - someDelta) or passing a negative TimeSpan computed at runtime (e.g. a deadline that has already passed, or subtracting durations in the wrong order).","commonSituations":"Computing a window size from configuration or telemetry where the value can go negative; subtracting a later timestamp from an earlier one; typo like TimeSpan.FromSeconds(-1) in tests; unit misconversion (milliseconds vs seconds) yielding negative values.","solutions":["Clamp or validate the TimeSpan before calling Buffer, e.g. Math.Max(TimeSpan.Zero, computed)","Trace where the TimeSpan is computed and fix the arithmetic so the window is non-negative","If the intent was an immediate close/open cycle, use TimeSpan.Zero, which is valid"],"exampleFix":"// before\nvar window = end - start; // can be negative if start > end\nobservable.Buffer(window);\n// after\nvar window = end > start ? end - start : TimeSpan.Zero;\nobservable.Buffer(window);","handlingStrategy":"validation","validationCode":"if (source == null) throw new ArgumentNullException(nameof(source));\nif (timeSpan < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(timeSpan));","typeGuard":"static bool IsValidWindow(TimeSpan t) => t >= TimeSpan.Zero;","tryCatchPattern":"try { source.Buffer(window); }\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"timeSpan\")\n{\n    logger.LogWarning(\"Invalid buffer window {Window}, falling back to 1s\", window);\n    source.Buffer(TimeSpan.FromSeconds(1));\n}","preventionTips":["Always wrap computed TimeSpans in Math.Max(TimeSpan.Zero, ...) before passing to time-based Rx operators","Use TimeSpan.From* factory methods with validated inputs instead of raw constructor arithmetic","Add Debug.Assert(t >= TimeSpan.Zero) at duration-producing boundaries"],"tags":["csharp","rx","argument-out-of-range","timespan"],"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"}