{"record":{"id":"4905d29b30bda9a4","repo":"dotnet/reactive","slug":"throw-new-argumentoutofrangeexception-nameof-period","errorCode":null,"errorMessage":"throw new ArgumentOutOfRangeException(nameof(period));","messagePattern":"throw new ArgumentOutOfRangeException\\(nameof\\(period\\)\\);","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs","lineNumber":2046,"sourceCode":"        /// <param name=\"dueTime\">Absolute time at which to produce the value. If this value is less than or equal to DateTimeOffset.UtcNow, the timer will fire as soon as possible.</param>\n        /// <returns>An observable sequence that produces a value at due time.</returns>\n        public static IObservable<long> Timer(DateTimeOffset dueTime)\n        {\n            return s_impl.Timer(dueTime);\n        }\n\n        /// <summary>\n        /// Returns an observable sequence that periodically produces a value after the specified initial relative due time has elapsed.\n        /// </summary>\n        /// <param name=\"dueTime\">Relative time at which to produce the first value. If this value is less than or equal to TimeSpan.Zero, the timer will fire as soon as possible.</param>\n        /// <param name=\"period\">Period to produce subsequent values. If this value is equal to TimeSpan.Zero, the timer will recur as fast as possible.</param>\n        /// <returns>An observable sequence that produces a value after due time has elapsed and then after each period.</returns>\n        /// <exception cref=\"ArgumentOutOfRangeException\"><paramref name=\"period\"/> is less than TimeSpan.Zero.</exception>\n        public static IObservable<long> Timer(TimeSpan dueTime, TimeSpan period)\n        {\n            if (period < TimeSpan.Zero)\n            {\n                throw new ArgumentOutOfRangeException(nameof(period));\n            }\n\n            return s_impl.Timer(dueTime, period);\n        }\n\n        /// <summary>\n        /// Returns an observable sequence that periodically produces a value starting at the specified initial absolute due time.\n        /// </summary>\n        /// <param name=\"dueTime\">Absolute time at which to produce the first value. If this value is less than or equal to DateTimeOffset.UtcNow, the timer will fire as soon as possible.</param>\n        /// <param name=\"period\">Period to produce subsequent values. If this value is equal to TimeSpan.Zero, the timer will recur as fast as possible.</param>\n        /// <returns>An observable sequence that produces a value at due time and then after each period.</returns>\n        /// <exception cref=\"ArgumentOutOfRangeException\"><paramref name=\"period\"/> is less than TimeSpan.Zero.</exception>\n        public static IObservable<long> Timer(DateTimeOffset dueTime, TimeSpan period)\n        {\n            if (period < TimeSpan.Zero)\n            {\n                throw new ArgumentOutOfRangeException(nameof(period));\n            }","sourceCodeStart":2028,"sourceCodeEnd":2064,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs#L2028-L2064","documentation":"Observable.Timer(TimeSpan dueTime, TimeSpan period) throws ArgumentOutOfRangeException when period is negative, because a repeating timer cannot have a negative interval between emissions. TimeSpan.Zero is allowed (indefinite repetitions as fast as the scheduler permits), but any value below Zero is rejected eagerly.","triggerScenarios":"Calling Observable.Timer(dueTime, TimeSpan.FromMilliseconds(-1)) or computing the period from an expression that yields a negative TimeSpan (e.g. subtracting timestamps in the wrong order, or a config value parsed with a negative sign).","commonSituations":"Polling intervals read from configuration where the value is negative or the subtraction of due dates inverts order; unit tests using negative delays; arithmetic like (a - b) where a < b.","solutions":["Pass a non-negative TimeSpan for period (use TimeSpan.Zero for continuous repetitions)","Validate or clamp the configured interval: if (period < TimeSpan.Zero) period = TimeSpan.Zero","Fix the calculation producing the negative TimeSpan (check operand order in subtractions)"],"exampleFix":"// before\nvar period = TimeSpan.FromSeconds(target) - TimeSpan.FromSeconds(current); // can be negative\nvar timer = Observable.Timer(dueTime, period);\n// after\nvar period = TimeSpan.FromSeconds(Math.Max(0, target - current));\nvar timer = Observable.Timer(dueTime, period);","handlingStrategy":"validation","validationCode":"if (period < TimeSpan.Zero)\n    throw new ArgumentOutOfRangeException(nameof(period));\nvar timer = Observable.Timer(dueTime, period);","typeGuard":"bool isValid = period >= TimeSpan.Zero;","tryCatchPattern":"try\n{\n    timer = Observable.Timer(dueTime, period);\n}\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"period\")\n{\n    timer = Observable.Timer(dueTime, TimeSpan.Zero);\n}","preventionTips":["Clamp computed intervals with Math.Max(TimeSpan.Zero, interval)","Validate configured durations at load time, rejecting negatives early","Watch timestamp subtraction order — (a - b) goes negative when a < b"],"tags":["csharp","rx","argument-out-of-range","timer"],"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"}