dotnet/wpf · error · InvalidOperationException

SR.NotAllowedToAccessStagingArea

Error message

SR.NotAllowedToAccessStagingArea

What it means

ProcessInputEventArgs.PushInput(InputEventArgs, StagingAreaInputItem) throws InvalidOperationException when the input staging area is not currently accessible. WPF only allows staging-area manipulation from inside an input event handler (e.g. PreProcessInput/PreNotifyInput/PostProcessInput) that is running on the thread's InputManager. Outside that window _allowAccessToStagingArea is false and the call is rejected.

Solutions

  1. Move the PushInput call inside the PreProcessInput/PostProcessInput handler where the args were delivered.
  2. Never cache ProcessInputEventArgs; perform all staging-area work synchronously within the handler.
  3. If you must defer work, capture the InputEventArgs payload instead and re-post input via InputManager.Current.ProcessInput on the dispatcher thread.
  4. Ensure the code runs on the same thread as the InputManager's dispatcher.

Example fix

// before
void OnPostProcessInput(object sender, ProcessInputEventArgs e)
{
    Dispatcher.BeginInvoke(() => e.PushInput(myInput, null)); // throws
}

// after
void OnPostProcessInput(object sender, ProcessInputEventArgs e)
{
    e.PushInput(myInput, null); // do it synchronously inside the handler
}
Defensive patterns

Strategy: validation

Validate before calling

// Only call inside PreProcessInput/PreNotifyInput/PostProcessInput handlers.
void OnPostProcessInput(object sender, ProcessInputEventArgs e)
{
    e.PushInput(newInput, null); // safe: inside handler
}

Type guard

bool CanUseStagingArea(ProcessInputEventArgs e, out bool allowed)
{
    // Access is granted only during input-event dispatch; there is no public
    // flag, so enforce it structurally: only call from within the handler.
    allowed = IsInsideInputEventHandler();
    return allowed;
}

Try / catch

try
{
    e.PushInput(input, promote);
}
catch (InvalidOperationException ex)
{
    // not in an input handler; defer via InputManager.Current.ProcessInput
    Log(ex);
}

Prevention

When it happens

Trigger: Calling PushInput on a ProcessInputEventArgs instance outside a PreProcessInput/PreNotifyInput/PostProcessInput event handler, from a different thread than the input manager's dispatcher, or after the handler's event dispatch has completed (e.g. stashing the args object and using it later).

Common situations: Developers cache ProcessInputEventArgs from an InputManager event and reuse it asynchronously (Dispatcher.BeginInvoke), or call PushInput from a background thread, or attempt staging-area mutation from an unrelated event like a timer tick.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/ProcessInputEventArgs.cs:50

        /// <summary>
        ///     Pushes an input event onto the top of the staging area.
        /// </summary>
        /// <param name="input">
        ///     The input event to place on the staging area.  This may not
        ///     be null, and may not already exist in the staging area.
        /// </param>
        /// <param name="promote">
        ///     An existing staging area item to promote the state from.
        /// </param>
        /// <returns>
        ///     The staging area input item that wraps the specified input.
        /// </returns>
        public StagingAreaInputItem PushInput(InputEventArgs input, 
                                              StagingAreaInputItem promote) // Note: this should be a bool, and always use the InputItem available on these args.
        {
            if(!_allowAccessToStagingArea)
            {
                throw new InvalidOperationException(SR.NotAllowedToAccessStagingArea);
            }
            
            return this.UnsecureInputManager.PushInput(input, promote);
        }

        /// <summary>
        ///     Pushes an input event onto the top of the staging area.
        /// </summary>
        /// <param name="input">
        ///     The input event to place on the staging area.  This may not
        ///     be null, and may not already exist in the staging area.
        /// </param>
        /// <returns>
        ///     The specified staging area input item.
        /// </returns>      
        public StagingAreaInputItem PushInput(StagingAreaInputItem input)
        {
            if(!_allowAccessToStagingArea)

View on GitHub (pinned to 81131a70a4)