AvaloniaUI/Avalonia · error · ArgumentException

Cannot raise an event whose RoutedEvent is null.

Error message

Cannot raise an event whose RoutedEvent is null.

What it means

RaiseEvent dispatches a RoutedEventArgs along the event route, which is built from e.RoutedEvent. If RoutedEvent is null the route cannot be constructed (there is no event identity), so RaiseEvent throws ArgumentException. This catches a common mistake: raising an args object that never had its event set.

Source

Thrown at src/Avalonia.Base/Interactivity/Interactive.cs:123

        /// <param name="handler">The handler.</param>
        public void RemoveHandler<TEventArgs>(RoutedEvent<TEventArgs> routedEvent, EventHandler<TEventArgs>? handler)
            where TEventArgs : RoutedEventArgs
        {
            if (handler is not null)
                RemoveHandler(routedEvent, (Delegate)handler);
        }

        /// <summary>
        /// Raises a routed event.
        /// </summary>
        /// <param name="e">The event args.</param>
        public void RaiseEvent(RoutedEventArgs e)
        {
            e = e ?? throw new ArgumentNullException(nameof(e));

            if (e.RoutedEvent == null)
            {
                throw new ArgumentException("Cannot raise an event whose RoutedEvent is null.");
            }

            using var route = BuildEventRoute(e.RoutedEvent);
            route.RaiseEvent(this, e);
        }

        /// <summary>
        /// Builds an event route for a routed event.
        /// </summary>
        /// <param name="e">The routed event.</param>
        /// <returns>An <see cref="EventRoute"/> describing the route.</returns>
        /// <remarks>
        /// Usually, calling <see cref="RaiseEvent(RoutedEventArgs)"/> is sufficient to raise a routed
        /// event, however there are situations in which the construction of the event args is expensive
        /// and should be avoided if there are no handlers for an event. In these cases you can call
        /// this method to build the event route and check the <see cref="EventRoute.HasHandlers"/>
        /// property to see if there are any handlers registered on the route. If there are, call
        /// <see cref="EventRoute.RaiseEvent(Interactive, RoutedEventArgs)"/> to raise the event.

View on GitHub (pinned to 11c5427268)

Solutions

  1. Always set RoutedEvent before raising: `e.RoutedEvent = MyControl.SomeEvent; control.RaiseEvent(e);`.
  2. Use the RoutedEventArgs constructor that takes the RoutedEvent: `new RoutedEventArgs(MyControl.SomeEvent)`.
  3. Null-check `e.RoutedEvent` (or the static event field) before raising.

Example fix

// before:
control.RaiseEvent(new RoutedEventArgs()); // RoutedEvent null -> throws

// after:
control.RaiseEvent(new RoutedEventArgs(MyControl.TappedEvent));
// or:
var e = new RoutedEventArgs { RoutedEvent = MyControl.TappedEvent };
control.RaiseEvent(e);
Defensive patterns

Strategy: validation

Validate before calling

if (e.RoutedEvent is null)
    throw new ArgumentException("RoutedEventArgs needs a RoutedEvent.");
control.RaiseEvent(e);

Type guard

static bool HasEvent(RoutedEventArgs e) => e.RoutedEvent is not null;

Prevention

When it happens

Trigger: Calling `control.RaiseEvent(new RoutedEventArgs())` without assigning `.RoutedEvent = SomeClass.SomeEvent`. Passing a reused/blank RoutedEventArgs whose RoutedEvent is null.

Common situations: Constructing RoutedEventArgs via the parameterless constructor and forgetting to set RoutedEvent. Reusing an event-args pool object that was reset. Custom controls raising an event field that is null.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/a2ffcd73f860b244. Report an issue: GitHub.