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

  1. Match the handler type to the event: use RoutedEvent.HandlerType to create the correct delegate
  2. Use the strongly-typed AddXXXHandler convenience method generated for the event instead of raw AddHandler
  3. 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

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


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)