dotnet/wpf · error · InvalidOperationException

SR.Invalid_IInputElement (oldFocus.GetType())

Error message

SR.Invalid_IInputElement (oldFocus.GetType())

What it means

The KeyboardFocusChangedEventArgs constructor validates oldFocus via InputElement.IsValid and throws InvalidOperationException(SR.Invalid_IInputElement, oldFocus.GetType()) if it is non-null but is not a valid IInputElement — i.e. it is neither a ContentElement, nor a UIElement (or its valid subclasses) that WPF's input system can target. The keyboard input system can only raise focus events against these element types.

Solutions

  1. Derive the focus element from UIElement (or ContentElement for document content) instead of implementing IInputElement directly.
  2. Pass null if there is no previous focus element rather than a placeholder object.
  3. Use InputElement.IsValid(element) in a guard before constructing the event args.
  4. Replace test mocks with real UIElement instances or derived test doubles.

Example fix

// before
class MyFocusTarget : IInputElement { ... }
var args = new KeyboardFocusChangedEventArgs(kb, ts, new MyFocusTarget(), newFocus);
// after
class MyFocusTarget : UIElement { ... }
var args = new KeyboardFocusChangedEventArgs(kb, ts, new MyFocusTarget(), newFocus);
Defensive patterns

Strategy: type-guard

Validate before calling

if (oldFocus != null && !InputElement.IsValid(oldFocus))
    throw new InvalidOperationException($"Invalid focus element: {oldFocus.GetType()}");

Type guard

static bool IsValidFocusElement(IInputElement e) => e is null || InputElement.IsValid(e);
// or without internals: e is UIElement or e is ContentElement

Try / catch

try { args = new KeyboardFocusChangedEventArgs(kb, ts, oldFocus, newFocus); }
catch (InvalidOperationException ex)
{ logger.LogError("Invalid focus element: {Msg}", ex.Message); args = null; }

Prevention

When it happens

Trigger: new KeyboardFocusChangedEventArgs(keyboard, timestamp, oldFocus, newFocus) with a non-null oldFocus that is a custom object implementing IInputElement directly instead of deriving from UIElement/ContentElement.

Common situations: Custom framework classes implementing IInputElement manually; passing mock objects in unit tests; passing elements from a different presentation source or a non-WPF object that merely implements the interface.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/FocusChangedEventArgs.cs:29

        /// <summary>
        ///     Constructs an instance of the KeyboardFocusChangedEventArgs class.
        /// </summary>
        /// <param name="keyboard">
        ///     The logical keyboard device associated with this event.
        /// </param>
        /// <param name="timestamp">
        ///     The time when the input occurred.
        /// </param>
        /// <param name="oldFocus">
        ///     The element that previously had focus.
        /// </param>
        /// <param name="newFocus">
        ///     The element that now has focus.
        /// </param>
        public KeyboardFocusChangedEventArgs(KeyboardDevice keyboard, int timestamp, IInputElement oldFocus, IInputElement newFocus) : base(keyboard, timestamp)
        {
            if (oldFocus != null && !InputElement.IsValid(oldFocus))
                throw new InvalidOperationException(SR.Format(SR.Invalid_IInputElement, oldFocus.GetType()));

            if (newFocus != null && !InputElement.IsValid(newFocus))
                throw new InvalidOperationException(SR.Format(SR.Invalid_IInputElement, newFocus.GetType()));

            _oldFocus = oldFocus;
            _newFocus = newFocus;
        }

        /// <summary>
        ///     The element that previously had focus.
        /// </summary>
        public IInputElement OldFocus
        {
            get {return _oldFocus;}
        }

        /// <summary>
        ///     The element that now has focus.

View on GitHub (pinned to 81131a70a4)