dotnet/wpf · error · InvalidOperationException
The Dispatcher failed to schedule a request for processing.
Error message
The Dispatcher failed to schedule a request for processing.
What it means
When Dispatcher fails to schedule a background work item for request processing (e.g. the ThreadPool or timer post fails), it consults BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure. If the app opted into 'Throw', an InvalidOperationException is raised; 'Continue' swallows it and 'Reset' retries by clearing the posted-processing flag.
Solutions
- Change the preference to HandleDispatcherRequestProcessingFailureOptions.Reset or Continue if strict throwing is not required
- Set the preference as early as possible (it must be set before the Dispatcher is used, typically at startup)
- Investigate why scheduling failed: thread-pool exhaustion, AppDomain/runtime shutdown, or low memory
- Retry the Dispatcher operation after the transient condition clears
Example fix
// before
BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure =
BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailureOptions.Throw;
// after
BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure =
BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailureOptions.Reset; Defensive patterns
Strategy: try-catch
Validate before calling
// verify the compatibility preference at startup var mode = BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure; Debug.Assert(mode != BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailureOptions.Throw || Debugger.IsAttached);
Try / catch
try
{
dispatcher.InvokeAsync(work);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("failed to schedule"))
{
logger.LogError(ex, "Dispatcher request processing could not be scheduled");
} Prevention
- Set HandleDispatcherRequestProcessingFailure once, at app startup, before any Dispatcher use
- Prefer Reset for production, Throw only under a debugger/tests
- Watch thread-pool health (ThreadPool.ThreadCount, queue lengths)
- Avoid scheduling dispatcher work during shutdown
When it happens
Trigger: QueueUserWorkItem/Timer scheduling fails inside the Dispatcher's request-processing path while BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure is set to HandleDispatcherRequestProcessingFailureOptions.Throw.
Common situations: Apps that set the compatibility switch for strict failure handling (common in test suites or reliability-sensitive services), especially under thread-pool starvation or when the runtime is shutting down.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- ElementNotAvailableException
- Invalid priority range order.
- Invalid priority value.
- Invalid priority value.
- parameter
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/dd97a06ac33e3eae.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Threading/Dispatcher.cs:2482
// keep the list from growing too large
// (although usually it will have only one entry)
if (list.Count > 1000)
{
// keep the earliest and latest failures
list.RemoveRange(100, list.Count - 200);
// acknowledge the gap
list.Insert(100, "... entries removed to conserve memory ...");
}
}
// handle the failure, according to app's preference
switch (BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailure)
{
case BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailureOptions.Continue:
break;
case BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailureOptions.Throw:
throw new InvalidOperationException(SR.DispatcherRequestProcessingFailed);
case BaseCompatibilityPreferences.HandleDispatcherRequestProcessingFailureOptions.Reset:
_postedProcessingType = PROCESS_NONE;
break;
}
}
internal void PromoteTimers(int currentTimeInTicks)
{
try
{
List<DispatcherTimer> timers = null;
long timersVersion = 0;
lock(_instanceLock)
{
if(!_hasShutdownFinished) // Could be a non-dispatcher thread, lock to read
{
if(_dueTimeFound && _dueTimeInTicks - currentTimeInTicks <= 0)View on GitHub (pinned to 81131a70a4)