dotnet/wpf · error · ArgumentException

Invalid priority value.

Error message

Invalid priority value.

What it means

DispatcherTimer.Initialize validates the priority twice: Dispatcher.ValidatePriority checks the value is a defined DispatcherPriority, and then Initialize rejects DispatcherPriority.Inactive specifically, because a timer with Inactive priority would never be processed. An invalid or Inactive priority throws ArgumentException/InvalidOperationException from the constructor.

Solutions

  1. Pass a valid active priority such as DispatcherPriority.Normal or Background - never Inactive
  2. Validate any config/interop integer with Enum.IsDefined(typeof(DispatcherPriority), value) before casting
  3. Use timer.IsEnabled = false to pause a timer instead of Inactive priority
  4. Centralize priority parsing in one helper that rejects unknown values early

Example fix

// before
var prio = (DispatcherPriority)configPriority; // e.g. 99 or Inactive
var timer = new DispatcherTimer(interval, prio, OnTick, dispatcher);
// after
var prio = Enum.IsDefined(typeof(DispatcherPriority), configPriority)
    && (DispatcherPriority)configPriority != DispatcherPriority.Inactive
        ? (DispatcherPriority)configPriority : DispatcherPriority.Normal;
var timer = new DispatcherTimer(interval, prio, OnTick, dispatcher);
Defensive patterns

Strategy: validation

Validate before calling

if (!Enum.IsDefined(typeof(DispatcherPriority), priorityValue) ||
    (DispatcherPriority)priorityValue == DispatcherPriority.Inactive)
    throw new ArgumentException(nameof(priorityValue));

Type guard

bool IsValidTimerPriority(DispatcherPriority p) =>
    Enum.IsDefined(p) && p != DispatcherPriority.Inactive;

Try / catch

try
{
    var timer = new DispatcherTimer(interval, priority, callback, dispatcher);
}
catch (ArgumentException ex)
{
    logger.LogError(ex, "Invalid timer priority {Priority}", priority);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("priority"))
{
    // Inactive priority passed; choose an active priority
}

Prevention

When it happens

Trigger: new DispatcherTimer(TimeSpan, (DispatcherPriority)99, callback, dispatcher) with an undefined priority value, or new DispatcherTimer(..., DispatcherPriority.Inactive, ...).

Common situations: Casting raw ints from config or interop into DispatcherPriority, refactoring code that stored priorities as numbers, or passing Inactive intending 'paused' semantics (which is IsEnabled's job).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

            get
            {
                return _tag;
            }

            set
            {
                _tag = value;
            }
        }


        private void Initialize(Dispatcher dispatcher, DispatcherPriority priority, TimeSpan interval)
        {
            // Note: all callers of this have a "priority" parameter.
            Dispatcher.ValidatePriority(priority, "priority");
            if(priority == DispatcherPriority.Inactive)
            {
                throw new ArgumentException(SR.InvalidPriority, nameof(priority));
            }

            _dispatcher = dispatcher;
            _priority = priority;
            _interval = interval;
        }
        
        private void Restart()
        {
            lock(_instanceLock)
            {
                if (_operation != null)
                {
                    // Timer has already been restarted, e.g. Start was called form the Tick handler.
                    return;
                }

                // BeginInvoke a new operation.

View on GitHub (pinned to 81131a70a4)