dotnet/wpf · error · ArgumentException

SR.OnlyAcceptsKeyMessages

Error message

SR.OnlyAcceptsKeyMessages

What it means

HwndKeyboardInputProvider.GetKeyUpKeyDown translates only keyboard key messages (WM_KEYDOWN/WM_SYSKEYDOWN/WM_KEYUP/WM_SYSKEYUP) into RawKeyboardActions. Any other WindowMessage passed to it is a programming error, so it throws ArgumentException with SR.OnlyAcceptsKeyMessages. The library uses this as an internal contract check on the message-filtering path.

Solutions

  1. Ensure only WM_KEYDOWN/WM_SYSKEYDOWN/WM_KEYUP/WM_SYSKEYUP messages are routed to this code path; filter other messages before calling.
  2. If you control the call site, branch on msg first and handle non-key messages separately instead of passing them through.
  3. Update any custom AddHook handler so it does not return RawKeyboardActions for messages it does not recognize.

Example fix

// before
var action = GetKeyUpKeyDown(msg); // throws for WM_CHAR etc.
// after
if (msg == WindowMessage.WM_KEYDOWN || msg == WindowMessage.WM_KEYUP ||
    msg == WindowMessage.WM_SYSKEYDOWN || msg == WindowMessage.WM_SYSKEYUP)
{
    var action = GetKeyUpKeyDown(msg);
}
Defensive patterns

Strategy: validation

Validate before calling

static bool IsKeyMessage(WindowMessage msg) =>
    msg == WindowMessage.WM_KEYDOWN || msg == WindowMessage.WM_KEYUP ||
    msg == WindowMessage.WM_SYSKEYDOWN || msg == WindowMessage.WM_SYSKEYUP;

Try / catch

try
{
    var action = GetKeyUpKeyDown(msg);
}
catch (ArgumentException)
{
    // msg was not a key message; ignore or log
}

Prevention

When it happens

Trigger: Calling GetKeyUpKeyDown (directly or through the keyboard input provider pipeline) with a WindowMessage that is not one of WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, or WM_SYSKEYUP — typically a custom message filter or subclassing WndProc forwarding non-key messages.

Common situations: Custom HwndSource hooks/addhooks that forward arbitrary messages (e.g. WM_CHAR, WM_KEYUP variants like WM_UNICHAR) into the keyboard processing path; automation or testing frameworks calling the internal translation with synthetic messages.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndKeyboardInputProvider.cs:694

                modifierKeys |= ModifierKeys.Control;
            }

            keyState = UnsafeNativeMethods.GetKeyState(NativeMethods.VK_MENU);
            if((keyState & 0x8000) == 0x8000)
            {
                modifierKeys |= ModifierKeys.Alt;
            }

            return modifierKeys;
        }

        private RawKeyboardActions GetKeyUpKeyDown(WindowMessage msg)
        {
            if(  msg == WindowMessage.WM_KEYDOWN || msg == WindowMessage.WM_SYSKEYDOWN )
                return RawKeyboardActions.KeyDown;
            if(  msg == WindowMessage.WM_KEYUP || msg == WindowMessage.WM_SYSKEYUP )
                return RawKeyboardActions.KeyUp;
            throw new ArgumentException(SR.OnlyAcceptsKeyMessages);
        }

        private void PossiblyDeactivate(IntPtr hwndFocus)
        {
            Debug.Assert( null != _source );

            // We are now longer active ourselves, but it is possible that the
            // window the keyboard is going to intereact with is in the same
            // Dispatcher as ourselves.  If so, we don't want to deactivate the
            // keyboard input stream because the other window hasn't activated
            // it yet, and it may result in the input stream "flickering" between
            // active/inactive/active.  This is ugly, so we try to supress the
            // uneccesary transitions.
            //
            bool deactivate = !IsOurWindow(hwndFocus);

            // This window itself should not be active anymore.
            _active = false;

View on GitHub (pinned to 81131a70a4)