dotnet/wpf · error · InvalidOperationException

SR.Stylus_CanOnlyCallForDownMoveOrUp

Error message

SR.Stylus_CanOnlyCallForDownMoveOrUp

What it means

NotifyWhenProcessed lets a StylusPlugIn request a callback after the PreviewStylus* event has traversed the application. It only works while the plug-in is servicing a Down/Move/Up raw input, when the ambient _currentNotifyPlugIn is set; otherwise WPF throws this InvalidOperationException.

Solutions

  1. Call NotifyWhenProcessed synchronously inside OnStylusDown, OnStylusMove, or OnStylusUp only
  2. If a deferred callback is needed, capture the data in the handler and use NotifyWhenProcessed there, scheduling your own work from the resulting callback
  3. Remove calls from non-Down/Move/Up handlers (Enter/Leave/InRange/OutOfRange) and use other mechanisms (e.g. element events) there

Example fix

// before
protected override void OnStylusInRange(RawStylusInput rawStylusInput)
{
    rawStylusInput.NotifyWhenProcessed(this); // throws
}
// after
protected override void OnStylusMove(RawStylusInput rawStylusInput)
{
    rawStylusInput.NotifyWhenProcessed(this); // valid: Down/Move/Up only
}
Defensive patterns

Strategy: try-catch

Try / catch

try { rawStylusInput.NotifyWhenProcessed(data); } catch (InvalidOperationException) { /* not in Down/Move/Up dispatch; handle inline instead */ }

Prevention

When it happens

Trigger: Calling NotifyWhenProcessed outside the dynamic call stack of OnStylusDown/OnStylusMove/OnStylusUp — e.g. storing the RawStylusInput and calling later, or calling from OnStylusEnter/OnStylusLeave/OnStylusInRange/OnStylusOutOfRange or from arbitrary app code.

Common situations: Deferring the call to a dispatcher work item or a timer instead of calling it synchronously inside the stylus event handler; assuming it works for hover events like InRange/OutOfRange where no notification is supported.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Common/RawStylusInput.cs:121

                throw new ArgumentException(SR.IncompatibleStylusPointDescriptions, nameof(stylusPoints));
            }
            if (stylusPoints.Count == 0)
            {
                throw new ArgumentException(SR.Stylus_StylusPointsCantBeEmpty, nameof(stylusPoints));
            }

            _stylusPoints = stylusPoints.Clone();
        }

        /// <summary>
        /// Returns the RawStylusInputCustomDataList used to notify plugins before  
        /// PreviewStylus event has been processed by application.
        /// </summary>
        public void NotifyWhenProcessed(object callbackData)
        {
            if (_currentNotifyPlugIn == null)
            {
                throw new InvalidOperationException(SR.Stylus_CanOnlyCallForDownMoveOrUp);
            }
            if (_customData == null)
            {
                _customData = new RawStylusInputCustomDataList();
            }
            _customData.Add(new RawStylusInputCustomData(_currentNotifyPlugIn, callbackData));
        }

        /// <summary>
        /// True if a StylusPlugIn has modifiedthe StylusPoints.
        /// </summary>
        internal bool StylusPointsModified
        {
            get 
            {
                return _stylusPoints != null;
            }
        }

View on GitHub (pinned to 81131a70a4)