{"record":{"id":"68f89ecebd2c192e","repo":"dotnet/reactive","slug":"interval","errorCode":null,"errorMessage":"interval","messagePattern":"interval","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs","lineNumber":855,"sourceCode":"        /// <param name=\"source\">Source sequence to sample.</param>\n        /// <param name=\"interval\">Interval at which to sample. If this value is equal to TimeSpan.Zero, the scheduler will continuously sample the stream.</param>\n        /// <returns>Sampled observable sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> is null.</exception>\n        /// <exception cref=\"ArgumentOutOfRangeException\"><paramref name=\"interval\"/> is less than TimeSpan.Zero.</exception>\n        /// <remarks>\n        /// Specifying a TimeSpan.Zero value for <paramref name=\"interval\"/> doesn't guarantee all source sequence elements will be preserved. This is a side-effect\n        /// of the asynchrony introduced by the scheduler, where the sampling action may not execute immediately, despite the TimeSpan.Zero due time.\n        /// </remarks>\n        public static IObservable<TSource> Sample<TSource>(this IObservable<TSource> source, TimeSpan interval)\n        {\n            if (source == null)\n            {\n                throw new ArgumentNullException(nameof(source));\n            }\n\n            if (interval < TimeSpan.Zero)\n            {\n                throw new ArgumentOutOfRangeException(nameof(interval));\n            }\n\n            return s_impl.Sample(source, interval);\n        }\n\n        /// <summary>\n        /// Samples the observable sequence at each interval, using the specified scheduler to run sampling timers.\n        /// Upon each sampling tick, the latest element (if any) in the source sequence during the last sampling interval is sent to the resulting sequence.\n        /// </summary>\n        /// <typeparam name=\"TSource\">The type of the elements in the source sequence.</typeparam>\n        /// <param name=\"source\">Source sequence to sample.</param>\n        /// <param name=\"interval\">Interval at which to sample. If this value is equal to TimeSpan.Zero, the scheduler will continuously sample the stream.</param>\n        /// <param name=\"scheduler\">Scheduler to run the sampling timer on.</param>\n        /// <returns>Sampled observable sequence.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"source\"/> or <paramref name=\"scheduler\"/> is null.</exception>\n        /// <exception cref=\"ArgumentOutOfRangeException\"><paramref name=\"interval\"/> is less than TimeSpan.Zero.</exception>\n        /// <remarks>\n        /// Specifying a TimeSpan.Zero value for <paramref name=\"interval\"/> doesn't guarantee all source sequence elements will be preserved. This is a side-effect","sourceCodeStart":837,"sourceCodeEnd":873,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs#L837-L873","documentation":"The Sample<TSource>(IObservable<TSource>, TimeSpan) operator throws ArgumentOutOfRangeException when the interval is negative (interval < TimeSpan.Zero). A sampling interval must be zero or positive; a negative due time is meaningless for a scheduler. Zero is allowed (samples as fast as the scheduler allows).","triggerScenarios":"Calling Observable.Sample(source, TimeSpan.FromSeconds(-1)) or any TimeSpan built from a negative value (e.g., subtracting DateTime values in the wrong order, or a config value parsed with a leading minus).","commonSituations":"Computing the interval from a date difference (later - earlier reversed); reading a negative interval from app settings; sign error when converting seconds to TimeSpan.From*; user-supplied config accepted without validation.","solutions":["Validate the interval before calling Sample and clamp/reject negatives.","Fix the interval computation so it cannot go negative (e.g., Math.Max(TimeSpan.Zero, diff)).","If you meant 'sample as often as possible', pass TimeSpan.Zero explicitly rather than a negative value."],"exampleFix":"// before\nvar interval = TimeSpan.FromSeconds(endSeconds - startSeconds); // can be negative\nvar sampled = source.Sample(interval); // ArgumentOutOfRangeException\n\n// after\nvar interval = TimeSpan.FromSeconds(Math.Max(0, endSeconds - startSeconds));\nvar sampled = source.Sample(interval);","handlingStrategy":"validation","validationCode":"if (interval < TimeSpan.Zero)\n    interval = TimeSpan.Zero; // or reject\nvar sampled = source.Sample(interval);","typeGuard":"static bool IsValidInterval(TimeSpan interval) => interval >= TimeSpan.Zero;","tryCatchPattern":"try\n{\n    var sampled = source.Sample(interval);\n}\ncatch (ArgumentOutOfRangeException ex)\n{\n    // log interval value; fall back to a default interval\n    var sampled = source.Sample(TimeSpan.FromSeconds(1));\n}","preventionTips":["Clamp computed durations with Math.Max(TimeSpan.Zero, value).","Reject negative duration config values at parse time.","Watch for DateTime subtraction order when deriving intervals."],"tags":["argument-out-of-range","rx","sample","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-23T08:17:48.524Z"}