dotnet/wpf · error · InvalidOperationException
SR.Format(SR.Invalid_IInputElement, _stylusOver.GetType())
Error message
SR.Format(SR.Invalid_IInputElement, _stylusOver.GetType())
What it means
WispLogic.ChangeStylusOver (WispLogic.cs:2204) throws InvalidOperationException(SR.Invalid_IInputElement) when the element currently under the stylus (_stylusOver) is neither a UIElement, ContentElement, nor UIElement3D. The WPF stylus input system only tracks those three input element types, so it fails fast instead of silently skipping hit-testable-event bookkeeping. It indicates an IInputElement reached internal stylus state that the stylus stack cannot handle.
Solutions
- Ensure the element under the stylus derives from UIElement, ContentElement, or UIElement3D rather than implementing IInputElement directly.
- Audit custom hit-test / input code that may assign a non-standard IInputElement to the stylus over-path.
- Reproduce under debugger and inspect _stylusOver.GetType() to identify the foreign element type and its creator.
Example fix
// before
class MyElement : FrameworkContentElement, IInputElement { } // ok, but a raw IInputElement is not
// after
class MyElement : UIElement { } // derive from a supported input element base Defensive patterns
Strategy: type-guard
Validate before calling
static bool CanBeStylusOver(object e) => e is UIElement || e is ContentElement || e is UIElement3D;
Type guard
static bool IsValidInputElement(IInputElement e) => e is UIElement || e is ContentElement || e is UIElement3D;
Try / catch
try { /* stylus over handling */ } catch (InvalidOperationException ex) when (ex.Message.Contains("IInputElement")) { /* log and fall back to mouse handling */ } Prevention
- Derive custom controls from UIElement/ContentElement/UIElement3D, never implement IInputElement directly
- Keep hit-test results within supported element types
- Test custom controls with a stylus/touch device
When it happens
Trigger: ChangeStylusOver is called (e.g. from stylus move/enter processing) with _stylusOver set to an object that passed IInputElement hit testing but fails the is-UIElement/is-ContentElement/is-UIElement3D pattern match — i.e. a custom IInputElement implementation feeding the stylus over-state.
Common situations: Custom control frameworks implementing IInputElement directly instead of deriving from UIElement/ContentElement; third-party presentation surfaces injecting foreign elements into the input tree; internal state corruption after re-templating or visual-tree mutations during stylus input.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- SR.Format(SR.Invalid_IInputElement…
- SR.Format(SR.Invalid_IInputElement, oldOver.GetType())
- SR.Format(SR.Invalid_IInputElement, relativeTo.GetType())
- SR.Format(SR.Invalid_IInputElement, _stylusOver.GetType())
- SR.InvalidStylusPointDescription
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/bc857bc65e5553b1.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/WispLogic.cs:2204
}
else if (o is ContentElement ce)
{
ce.IsEnabledChanged += _overIsEnabledChangedEventHandler;
// NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
//
// ce.IsVisibleChanged += _overIsVisibleChangedEventHandler;
// ce.IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
}
else if (o is UIElement3D uie3D)
{
uie3D.IsEnabledChanged += _overIsEnabledChangedEventHandler;
uie3D.IsVisibleChanged += _overIsVisibleChangedEventHandler;
uie3D.IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
}
else
{
throw new InvalidOperationException(SR.Format(SR.Invalid_IInputElement, _stylusOver.GetType()));
}
}
// Oddly enough, update the IsStylusOver property first. This is
// so any callbacks will see the more-common IsStylusOver property
// set correctly.
UIElement.StylusOverProperty.OnOriginValueChanged(oldOver as DependencyObject, _stylusOver as DependencyObject, ref _stylusOverTreeState);
// Invalidate the IsStylusDirectlyOver property.
if (oldOver != null)
{
o = oldOver as DependencyObject;
o.SetValue(UIElement.IsStylusDirectlyOverPropertyKey, false); // Same property for ContentElements
}
if (_stylusOver != null)
{
o = _stylusOver as DependencyObject;
o.SetValue(UIElement.IsStylusDirectlyOverPropertyKey, true); // Same property for ContentElementsView on GitHub (pinned to 81131a70a4)