dotnet/wpf · error · ArgumentException
SR.OnlyAcceptsKeyMessages
Error message
SR.OnlyAcceptsKeyMessages
What it means
This HwndSource member (the keyboard-sink message processing path) accepts only keyboard-related window messages; its switch statement whitelists messages such as WM_KEYDOWN/WM_KEYUP/WM_CHAR/WM_DEADCHAR and throws ArgumentException(SR.OnlyAcceptsKeyMessages) for anything else. It is a contract check that the caller only forwards messages this sink is meant to process.
Solutions
- Filter messages before calling: only route WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_CHAR, WM_DEADCHAR (and siblings the switch allows).
- In an AddHook handler, return early (don't call the processor) for messages you don't handle.
- Use the public HwndSource pipeline (WndProc) rather than calling internal processing methods with arbitrary messages.
Example fix
// before
void Hook(IntPtr hwnd, int msg, IntPtr w, IntPtr l, ref bool handled)
{
ProcessKeyboardMessage((WindowMessage)msg); // throws for WM_PAINT
}
// after
void Hook(IntPtr hwnd, int msg, IntPtr w, IntPtr l, ref bool handled)
{
switch ((WindowMessage)msg)
{
case WindowMessage.WM_KEYDOWN:
case WindowMessage.WM_KEYUP:
case WindowMessage.WM_CHAR:
ProcessKeyboardMessage((WindowMessage)msg);
break;
}
}
Defensive patterns
Strategy: validation
Validate before calling
static readonly HashSet<WindowMessage> Accepted = new() {
WindowMessage.WM_KEYDOWN, WindowMessage.WM_KEYUP,
WindowMessage.WM_SYSKEYDOWN, WindowMessage.WM_SYSKEYUP,
WindowMessage.WM_CHAR, WindowMessage.WM_DEADCHAR };
if (Accepted.Contains(msg)) ProcessKeyboardMessage(msg); Try / catch
try
{
ProcessKeyboardMessage(msg);
}
catch (ArgumentException)
{
// non-key message reached the keyboard path; ignore
} Prevention
- Whitelist key messages at the AddHook boundary.
- Return early from hooks for messages you don't own.
- Don't call internal processing methods with arbitrary WndProc traffic.
When it happens
Trigger: Forwarding a non-key WindowMessage (e.g. WM_MOUSEMOVE, WM_PAINT, or an application-defined message) into the sink's keyboard processing method instead of letting the normal WndProc dispatch handle it.
Common situations: Custom AddHook callbacks that forward every message to the sink unfiltered; testing/automation code synthesizing messages and calling the processor directly; forwarding messages from a parent window that include non-key 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/22d4c53bdcae1c8c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndSource.cs:2092
if (AccessKeyManager.IsKeyRegistered(this, text))
{
AccessKeyManager.ProcessKey(this, text, false);
// is it ok not to update _lastKeyboardMessage?
return true;
}
}
// these are OK
break;
case WindowMessage.WM_CHAR:
case WindowMessage.WM_DEADCHAR:
// these are OK
break;
default:
throw new ArgumentException(SR.OnlyAcceptsKeyMessages);
}
// We record the last message that was processed by us.
// This is also checked in WndProc processing to prevent double processing.
_lastKeyboardMessage = msg;
// The bubble will take care of access key processing for this HWND. Call
// the IKIS children unless we are in menu mode.
if (_keyboardInputSinkChildren != null && !IsInExclusiveMenuMode)
{
foreach ( HwndSourceKeyboardInputSite childSite in _keyboardInputSinkChildren )
{
if (((IKeyboardInputSite)childSite).Sink.OnMnemonic(ref msg, modifiers))
return true;
}
}
return false;
}View on GitHub (pinned to 81131a70a4)