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
- Call NotifyWhenProcessed synchronously inside OnStylusDown, OnStylusMove, or OnStylusUp only
- If a deferred callback is needed, capture the data in the handler and use NotifyWhenProcessed there, scheduling your own work from the resulting callback
- 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
- Call NotifyWhenProcessed only synchronously inside OnStylusDown/OnStylusMove/OnStylusUp
- Never stash RawStylusInput for later calls
- Use plug-in Enter/Leave/InRange/OutOfRange handlers without NotifyWhenProcessed
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
- SR.Format(SR.Invalid_IInputElement…
- SR.Format(SR.Invalid_IInputElement, oldCapture.GetType())
- SR.Format(SR.Invalid_IInputElement, oldCapture.GetType())
- SR.Format(SR.Invalid_IInputElement, oldOver.GetType())
- SR.Format(SR.Invalid_IInputElement, oldOver.GetType())
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)