dotnet/wpf · error · ArgumentException
SR.HandlerTypeIllegal
Error message
SR.HandlerTypeIllegal
What it means
EventHandlersStore.AddRoutedEventHandler validates that the delegate's signature matches the handler type declared for the routed event via RoutedEvent.IsLegalHandler. When the delegate type is incompatible with routedEvent.HandlerType it throws ArgumentException with SR.HandlerTypeIllegal. Called by AddDelegateToFireTrigger when wiring trigger handlers.
Solutions
- Pass a delegate of exactly routedEvent.HandlerType (cast/create a matching delegate)
- Check routedEvent.HandlerType before creating the delegate
- Use the typed CLR event accessor (e.g. element.MouseDown += ...) instead of store-level APIs
Example fix
// before store.AddRoutedEventHandler(Keyboard.KeyDownEvent, new RoutedEventHandler(OnKeyDown), false); // after store.AddRoutedEventHandler(Keyboard.KeyDownEvent, new KeyEventHandler(OnKeyDown), false);
Defensive patterns
Strategy: validation
Validate before calling
if (routedEvent.IsLegalHandler(handler)) { store.AddRoutedEventHandler(routedEvent, handler, handledEventsToo); } Type guard
bool IsLegalFor(RoutedEvent e, Delegate h) => e != null && h != null && e.IsLegalHandler(h);
Try / catch
try { store.AddRoutedEventHandler(evt, handler, false); } catch (ArgumentException) { /* wrong delegate type for evt.HandlerType */ } Prevention
- Match the delegate type to routedEvent.HandlerType exactly
- Prefer typed CLR event accessors over EventHandlersStore internals
- Never pass lambdas as plain Action/EventHandler delegates to routed-event plumbing
When it happens
Trigger: Calling AddRoutedEventHandler with a Delegate whose parameter/return types do not match routedEvent.HandlerType — e.g. passing a RoutedEventHandler to an event declared with KeyRoutedEventHandler, or a plain EventHandler for a routed event.
Common situations: Copy-pasting handler wiring code between different events; generic trigger frameworks adding delegates of the wrong type; API changes where an event's handler type was tightened.
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
- InvalidEnumArgumentException: routingStrategy
- SR.ClassTypeIllegal
- SR.HandlerTypeIllegal
- SR.HandlerTypeIllegal
- SR.Mismatched_RoutedEvent
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/61e269214ac654f5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/EventHandlersStore.cs:147
#endregion ExternalAPI
#region Operations
/// <summary>
/// Adds a routed event handler for the given
/// RoutedEvent to the store
/// </summary>
public void AddRoutedEventHandler(
RoutedEvent routedEvent,
Delegate handler,
bool handledEventsToo)
{
ArgumentNullException.ThrowIfNull(routedEvent);
ArgumentNullException.ThrowIfNull(handler);
if (!routedEvent.IsLegalHandler(handler))
{
throw new ArgumentException(SR.HandlerTypeIllegal);
}
// Create a new RoutedEventHandler
RoutedEventHandlerInfo routedEventHandlerInfo =
new RoutedEventHandlerInfo(handler, handledEventsToo);
// Get the entry corresponding to the given RoutedEvent
FrugalObjectList<RoutedEventHandlerInfo> handlers = (FrugalObjectList<RoutedEventHandlerInfo>)this[routedEvent];
if (handlers == null)
{
_entries[routedEvent.GlobalIndex] = handlers = new FrugalObjectList<RoutedEventHandlerInfo>(1);
}
// Add the RoutedEventHandlerInfo to the list
handlers.Add(routedEventHandlerInfo);
}
/// <summary>View on GitHub (pinned to 81131a70a4)