dotnet/wpf · error · ArgumentException
SR.KeyboardSinkMustBeAnElement
Error message
SR.KeyboardSinkMustBeAnElement
What it means
HwndSourceKeyboardInputSite's constructor requires the IKeyboardInputSink it wraps to also be a UIElement, because keyboard input routing in WPF depends on the sink having an element-based visual/hit-testing surface. If the sink is any other IKeyboardInputSink implementation, the constructor throws ArgumentException with resource key SR.KeyboardSinkMustBeAnElement naming the 'sink' parameter.
Solutions
- Make the sink derive from UIElement (e.g. subclass HwndHost or another UIElement) and implement IKeyboardInputSink there
- If the sink cannot be a UIElement, register it as a child sink via an existing UIElement sink's ChildKeyboardInputSinks instead of constructing the site directly
Example fix
// before
IKeyboardInputSink sink = new MyCustomSink();
var site = new HwndSourceKeyboardInputSite(source, sink); // throws
// after
class MySink : HwndHost, IKeyboardInputSink { ... }
var site = new HwndSourceKeyboardInputSite(source, new MySink()); Defensive patterns
Strategy: validation
Validate before calling
if (sink is not UIElement) throw new ArgumentException("sink must be a UIElement", nameof(sink));
var site = new HwndSourceKeyboardInputSite(source, sink); Type guard
bool IsValidSink(IKeyboardInputSink s) => s is UIElement;
Prevention
- Implement IKeyboardInputSink on UIElement-derived classes (HwndHost) only
- Never expose raw IKeyboardInputSink implementations to constructors expecting elements
- Check the sink type at the interop boundary before wiring keyboard sites
When it happens
Trigger: Calling new HwndSourceKeyboardInputSite(source, sink) where sink is a custom or third-party IKeyboardInputSink that does not derive from UIElement (source or sink being null throws a different error first).
Common situations: Developers implementing IKeyboardInputSink on a plain class or a Control-derived-non-UIElement type to host WinForms/Win32 interop content, then wiring it as the root sink for an HwndSource.
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
- 0x80070057
- ArgumentNullException (buffer/sourceBuffer was IntPtr.Zero)
- ArgumentOutOfRangeException (timeout was Duration.Automatic)
- Buffer address passed to GetText cannot be NULL.
- Collection_BadRank
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/e1cddb50646e9f8d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndSourceKeyboardInputSite.cs:16
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Windows.Input;
namespace System.Windows.Interop
{
internal class HwndSourceKeyboardInputSite : IKeyboardInputSite
{
public HwndSourceKeyboardInputSite(HwndSource source, IKeyboardInputSink sink)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(sink);
if (!(sink is UIElement))
{
throw new ArgumentException(SR.KeyboardSinkMustBeAnElement, nameof(sink));
}
_source = source;
_sink = sink;
_sink.KeyboardInputSite = this;
_sinkElement = sink as UIElement;
}
#region IKeyboardInputSite
/// <summary>
/// Unregisters a child KeyboardInputSink from this sink.
/// </summary>
/// <remarks>
/// Requires unmanaged code permission.
/// </remarks>
void IKeyboardInputSite.Unregister()View on GitHub (pinned to 81131a70a4)