dotnet/wpf · error · ArgumentOutOfRangeException

The period '' is invalid. Period must be non-negative and…

Error message

The period '' is invalid. Period must be non-negative and less than or equal to Int32.MaxValue milliseconds.

What it means

The DispatcherTimer constructor validates the interval TimeSpan: it must represent between 0 and Int32.MaxValue milliseconds. A negative interval throws ArgumentOutOfRangeException with the TimeSpanPeriodOutOfRange_TooSmall message (displayed here with an empty formatted period). The constructor cannot proceed with an unrepresentable period.

Solutions

  1. Pass a non-negative TimeSpan, e.g. TimeSpan.FromMilliseconds(0) or a positive duration
  2. Guard/clamp the configured value before constructing: if (interval < TimeSpan.Zero) interval = TimeSpan.Zero
  3. If an 'infinite' timer is intended, construct the timer without starting it (disable via IsEnabled) instead of using Timeout.InfiniteTimeSpan
  4. Fix the configuration/source that produced the negative value

Example fix

// before
var timer = new DispatcherTimer(Timeout.InfiniteTimeSpan, DispatcherPriority.Normal, OnTick, Dispatcher.CurrentDispatcher);
// after
var timer = new DispatcherTimer(TimeSpan.FromSeconds(30), DispatcherPriority.Normal, OnTick, Dispatcher.CurrentDispatcher);
Defensive patterns

Strategy: validation

Validate before calling

if (interval < TimeSpan.Zero || interval.TotalMilliseconds > Int32.MaxValue)
    throw new ArgumentOutOfRangeException(nameof(interval));

Type guard

bool IsValidTimerInterval(TimeSpan t) =>
    t >= TimeSpan.Zero && t.TotalMilliseconds <= Int32.MaxValue;

Try / catch

try
{
    var timer = new DispatcherTimer(interval, priority, callback, dispatcher);
}
catch (ArgumentOutOfRangeException ex)
{
    logger.LogError(ex, "Invalid timer interval: {Interval}", interval);
}

Prevention

When it happens

Trigger: new DispatcherTimer(TimeSpan.FromMilliseconds(-1), priority, callback, dispatcher) or any interval whose TotalMilliseconds < 0.

Common situations: Passing a TimeSpan from parsed configuration where the sign was lost, using Timeout.InfiniteTimeSpan (-1 ms) which is valid for System.Threading.Timer but not DispatcherTimer, or computing an interval by subtraction that underflows.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/9e37acb7e8694073. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Threading/DispatcherTimer.cs:72

        /// <param name="interval">
        ///     The interval to tick the timer after.
        /// </param>
        /// <param name="priority">
        ///     The priority to process the timer at.
        /// </param>
        /// <param name="callback">
        ///     The callback to call when the timer ticks.
        /// </param>
        /// <param name="dispatcher">
        ///     The dispatcher to use to process the timer.
        /// </param>
        public DispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHandler callback, Dispatcher dispatcher) // NOTE: should be Priority
        {
            ArgumentNullException.ThrowIfNull(callback);
            ArgumentNullException.ThrowIfNull(dispatcher);

            if (interval.TotalMilliseconds < 0)
                throw new ArgumentOutOfRangeException(nameof(interval), SR.TimeSpanPeriodOutOfRange_TooSmall);

            if (interval.TotalMilliseconds > Int32.MaxValue)
                throw new ArgumentOutOfRangeException(nameof(interval), SR.TimeSpanPeriodOutOfRange_TooLarge);

            Initialize(dispatcher, priority, interval);
            
            Tick += callback;
            Start();
        }

        /// <summary>
        ///     Gets the dispatcher this timer is associated with.
        /// </summary>
        public Dispatcher Dispatcher
        {
            get
            {
                return _dispatcher;

View on GitHub (pinned to 81131a70a4)