dotnet/wpf · error · ArgumentException
SR.HandlerTypeIllegal
Error message
SR.HandlerTypeIllegal
What it means
AddHandler(RoutedEvent, Delegate) validates that the supplied handler's signature matches the routed event's handler type (RoutedEvent.IsLegalHandler). When the delegate type does not match what the event expects, ArgumentException(SR.HandlerTypeIllegal) is thrown before the handler is added to the EventHandlersStore.
Solutions
- Match the handler type to the event: use RoutedEvent.HandlerType to create the correct delegate
- Use the strongly-typed AddXXXHandler convenience method generated for the event instead of raw AddHandler
- Verify with routedEvent.IsLegalHandler(handler) before calling AddHandler
Example fix
// before el.AddHandler(Keyboard.KeyDownEvent, new MouseEventHandler(OnMouse)); // after el.AddHandler(Keyboard.KeyDownEvent, new KeyEventHandler(OnKey));
Defensive patterns
Strategy: validation
Validate before calling
if (!routedEvent.IsLegalHandler(handler)) throw new ArgumentException($"Handler type {handler.GetType()} is not legal for {routedEvent.Name} (expects {routedEvent.HandlerType})."); Type guard
bool IsLegalFor(RoutedEvent e, Delegate d) => e.IsLegalHandler(d);
Try / catch
try { el.AddHandler(evt, handler); } catch (ArgumentException ex) when (ex.Message.Contains("HandlerType")) { /* fix delegate type */ } Prevention
- Prefer generated strongly-typed AddXXXHandler methods
- Check RoutedEvent.HandlerType before constructing delegates
- Keep handler signatures consistent across subscribe/unsubscribe
When it happens
Trigger: Calling UIElement.AddHandler (generated wrapper) with a delegate whose parameter/return signature does not match the RoutedEvent's HandlerType, e.g. attaching a MouseEventHandler to a Keyboard.KeyDownEvent.
Common situations: Copy-pasted handler registrations between similar events; refactors that changed a delegate type; wiring generated/late-bound events where the event-to-handler mapping was hand-typed.
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
- SR.BadFixedTextPosition
- SR.Collection_BadType
- SR.Format(SR.Animation_AnimationTimelineTypeMismatch…
- SR.Format(SR.Animation_AnimationTimelineTypeMismatch…
- SR.Format(SR.Collection_BadDestArray, this.GetType().Name)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/4a9fa6f76bfea5a4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/generators/Elements.cs:382
/// </param>
/// <param name="handledEventsToo">
/// Flag indicating whether or not the listener wants to
/// hear about events that have already been handled
/// </param>
public void AddHandler(
RoutedEvent routedEvent,
Delegate handler,
bool handledEventsToo)
{
// VerifyAccess();
ArgumentNullException.ThrowIfNull(routedEvent);
ArgumentNullException.ThrowIfNull(handler);
if (!routedEvent.IsLegalHandler(handler))
{
throw new ArgumentException(SR.HandlerTypeIllegal);
}
EnsureEventHandlersStore();
EventHandlersStore.AddRoutedEventHandler(routedEvent, handler, handledEventsToo);
OnAddHandler(routedEvent, handler);
}
/// <summary>
/// Notifies subclass of a new routed event handler. Note that this is
/// called once for each handler added, but OnRemoveHandler is only called
/// on the last removal.
/// </summary>
internal virtual void OnAddHandler(
RoutedEvent routedEvent,
Delegate handler)
{
}View on GitHub (pinned to 81131a70a4)