dotnet/wpf · error · InvalidOperationException

The DispatcherPriorityAwaiter is invalid.

Error message

The DispatcherPriorityAwaiter is invalid.

What it means

DispatcherPriorityAwaitable's awaiter (OnCompleted) throws InvalidOperationException if the underlying _dispatcher is null. This happens when the awaiter instance was created through a default/invalid path rather than via Dispatcher.InvokeAsync or BeginInvoke, so there is no dispatcher to post the continuation to.

Solutions

  1. Obtain the awaiter only from Dispatcher.InvokeAsync(...).Task.GetAwaiter() or Dispatcher.Yield(priority) - never construct/default it yourself
  2. Await the awaitable exactly once; create a new one for each yield point
  3. Verify the code path sets a valid Dispatcher before OnCompleted is invoked if implementing a custom awaitable
  4. Refactor to plain Task.Yield() plus InvokeAsync if the custom priority-yield is not strictly needed

Example fix

// before
var awaiter = default(DispatcherPriorityAwaitable).GetAwaiter();
await awaiter; // throws: invalid awaiter
// after
await Dispatcher.Yield(DispatcherPriority.Background);
Defensive patterns

Strategy: validation

Validate before calling

// Only obtain awaiters via supported APIs:
var awaitable = Dispatcher.Yield(DispatcherPriority.Background); // not default(...)

Type guard

bool isValidAwaiter(DispatcherPriorityAwaiter a) => a is not null; // default-constructed awaiters are invalid
// prefer: never construct/default the awaiter yourself

Try / catch

try
{
    await dispatcherYieldAwaitable;
}
catch (InvalidOperationException ex) when (ex.Message.Contains("DispatcherPriorityAwaiter is invalid"))
{
    // fix the awaitable source; do not retry the same invalid awaiter
}

Prevention

When it happens

Trigger: Awaiting a DispatcherPriorityAwaitable obtained outside the supported API surface, or awaiting the same awaiter twice after it was reset/default-constructed (internal _dispatcher field null).

Common situations: Misusing Dispatcher.Yield or a default(DispatcherPriorityAwaitable)-style path, or caching/reusing an awaiter across awaits in custom async helpers.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Threading/DispatcherPriorityAwaiter.cs:56

        }

        /// <summary>
        ///     This awaiter is just a proxy for queuing the continuations, it
        ///     never completes itself, so it doesn't have any result.
        /// </summary>
        public void GetResult()
        {
        }

        /// <summary>
        ///     This is called with the continuation, which is simply queued to
        ///     the Dispatcher at the priority specified to the constructor.
        /// </summary>
        public void OnCompleted(Action continuation)
        {
            if(_dispatcher == null)
            {
                throw new InvalidOperationException(SR.DispatcherPriorityAwaiterInvalid);
            }
            
            _dispatcher.InvokeAsync(continuation, _priority);
        }

        private readonly Dispatcher _dispatcher;
        private readonly DispatcherPriority _priority;
}
}

View on GitHub (pinned to 81131a70a4)