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
- Ensure only WM_KEYDOWN/WM_SYSKEYDOWN/WM_KEYUP/WM_SYSKEYUP messages are routed to this code path; filter other messages before calling.
- If you control the call site, branch on msg first and handle non-key messages separately instead of passing them through.
- 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
- Filter WindowMessages to the key-message set before keyboard translation.
- Don't forward raw WndProc messages unfiltered into keyboard processing.
- Centralize the message whitelist in one helper used by all hooks.
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
- SR.OnlyAcceptsKeyMessages
- " }} " element found. Expected fixed page element ( }} ).
- ' ' ContentType is not valid.
- ' ' ID is not a valid XSD ID.
- array
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)