dotnet/wpf · error · InvalidOperationException
SR.Format(SR.Invalid_IInputElement, oldOver.GetType())
Error message
SR.Format(SR.Invalid_IInputElement, oldOver.GetType())
What it means
WispStylusDevice.UpdateOverProperty (WispStylusDevice.cs:407) throws InvalidOperationException(SR.Invalid_IInputElement) when detaching event handlers (IsEnabledChanged, IsVisibleChanged, IsHitTestVisibleChanged) from oldOver — the previous stylus-over element — and oldOver is not UIElement, ContentElement, or UIElement3D. The over-state bookkeeping expects only those element kinds, so a foreign element in _stylusOver state fails fast.
Solutions
- Ensure all elements that can be under the stylus derive from UIElement, ContentElement, or UIElement3D.
- Inspect oldOver.GetType() in a debugger to find the source of the foreign element.
- Remove custom hit-test code that returns raw IInputElement implementations.
Example fix
// before
class Tile : DependencyObject, IInputElement { }
// after
class Tile : UIElement { } Defensive patterns
Strategy: type-guard
Validate before calling
static bool TracksStylusOver(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 transition */ } catch (InvalidOperationException ex) when (ex.Message.Contains("IInputElement")) { /* clear stylus state and fall back to mouse input */ } Prevention
- Keep all hit-testable elements within UIElement/ContentElement/UIElement3D hierarchy
- Avoid third-party IInputElement implementations in the visual tree
- Debug oldOver.GetType() early when integrating custom input frameworks
When it happens
Trigger: ChangeStylusOver transitions the stylus-over element while the stored previous element is a non-standard IInputElement, usually because it was accepted earlier without validation.
Common situations: Custom IInputElement implementations in the hit-test path; state corruption after visual-tree surgery during stylus moves; third-party input frameworks injecting elements.
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, _stylusOver.GetType())
- SR.Format(SR.Invalid_IInputElement…
- SR.Format(SR.Invalid_IInputElement, relativeTo.GetType())
- SR.Format(SR.Invalid_IInputElement, _stylusOver.GetType())
- ArgumentNullException: hitTestParameters
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/b63eec161ea49ca5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Wisp/WispStylusDevice.cs:407
}
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, oldOver.GetType()));
}
}
if (_stylusOver != null)
{
o = _stylusOver as DependencyObject;
if (o is UIElement uie)
{
uie.IsEnabledChanged += _overIsEnabledChangedEventHandler;
uie.IsVisibleChanged += _overIsVisibleChangedEventHandler;
uie.IsHitTestVisibleChanged += _overIsHitTestVisibleChangedEventHandler;
}
else if (o is ContentElement ce)
{
ce.IsEnabledChanged += _overIsEnabledChangedEventHandler;
// NOTE: there are no IsVisible or IsHitTestVisible properties for ContentElements.
//
// ce.IsVisibleChanged += _overIsVisibleChangedEventHandler;View on GitHub (pinned to 81131a70a4)