{"record":{"id":"75f5ba2d2fea8362","repo":"dotnet/reactive","slug":"argumentoutofrangeexception-period-specified-argument-was","errorCode":null,"errorMessage":"ArgumentOutOfRangeException: period (Specified argument was out of the range of valid values.)","messagePattern":"ArgumentOutOfRangeException: period \\(Specified argument was out of the range of valid values\\.\\)","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive.WindowsRuntime/System.Reactive.Concurrency/CoreDispatcherScheduler.cs","lineNumber":244,"sourceCode":"        /// <summary>\n        /// Schedules a periodic piece of work on the dispatcher, using a <see cref=\"DispatcherQueueTimer\"/> object.\n        /// </summary>\n        /// <typeparam name=\"TState\">The type of the state passed to the scheduled action.</typeparam>\n        /// <param name=\"state\">Initial state passed to the action upon the first iteration.</param>\n        /// <param name=\"period\">Period for running the work periodically.</param>\n        /// <param name=\"action\">Action to be executed, potentially updating the state.</param>\n        /// <returns>The disposable object used to cancel the scheduled recurring action (best effort).</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"action\"/> is <c>null</c>.</exception>\n        /// <exception cref=\"ArgumentOutOfRangeException\"><paramref name=\"period\"/> is less than <see cref=\"TimeSpan.Zero\"/>.</exception>\n        public IDisposable SchedulePeriodic<TState>(TState state, TimeSpan period, Func<TState, TState> action)\n        {\n            //\n            // According to MSDN documentation, the default is TimeSpan.Zero, so that's definitely valid.\n            // Empirical observation - negative values seem to be normalized to TimeSpan.Zero, but let's not go there.\n            //\n            if (period < TimeSpan.Zero)\n            {\n                throw new ArgumentOutOfRangeException(nameof(period));\n            }\n\n            if (action == null)\n            {\n                throw new ArgumentNullException(nameof(action));\n            }\n\n            var timer = CreateDispatcherQueue().CreateTimer();\n\n            var state1 = state;\n\n            timer.Tick += (o, e) =>\n            {\n                state1 = action(state1);\n            };\n\n            timer.Interval = period;\n            timer.Start();","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive.WindowsRuntime/System.Reactive.Concurrency/CoreDispatcherScheduler.cs#L226-L262","documentation":"SchedulePeriodic validates that the repetition period is non-negative; a negative TimeSpan is rejected with ArgumentOutOfRangeException naming period. WinRT dispatcher timers cannot meaningfully represent a negative tick interval, so the library fails fast rather than silently normalizing.","triggerScenarios":"Calling scheduler.SchedulePeriodic(state, TimeSpan.FromSeconds(-1), action) or computing a period from data that can go negative (e.g. remaining = deadline - now with clock skew).","commonSituations":"Dynamic poll intervals derived from configuration or measurements that underflow to negative values; sign errors when computing delays.","solutions":["Clamp the period: if (period < TimeSpan.Zero) period = TimeSpan.Zero; before calling.","Fix the interval computation so it cannot produce negative values.","Validate configured interval values at startup and reject non-positive settings early."],"exampleFix":"// before\nscheduler.SchedulePeriodic(state, TimeSpan.FromMilliseconds(timeoutMs), action); // timeoutMs can be negative\n// after\nvar period = TimeSpan.FromMilliseconds(Math.Max(0, timeoutMs));\nscheduler.SchedulePeriodic(state, period, action);","handlingStrategy":"validation","validationCode":"if (period < TimeSpan.Zero) period = TimeSpan.Zero;\nscheduler.SchedulePeriodic(state, period, action);","typeGuard":"bool IsValidPeriod(TimeSpan p) => p >= TimeSpan.Zero;","tryCatchPattern":"try { scheduler.SchedulePeriodic(state, period, action); }\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"period\")\n{ /* clamp period and retry */ }","preventionTips":["Clamp computed intervals with Math.Max(TimeSpan.Zero, value)","Validate configured intervals at startup","Watch for clock-skew arithmetic that can yield negatives"],"tags":["argument-out-of-range","csharp","scheduler","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"}