AvaloniaUI/Avalonia · error · InvalidCastException

eventArgsType must be derived from RoutedEventArgs.

Error message

eventArgsType must be derived from RoutedEventArgs.

What it means

Thrown by the RoutedEvent constructor when the eventArgsType argument does not derive from RoutedEventArgs. RoutedEvent is the metadata object backing Avalonia's tunneling/bubbling routed-event system, and every routed event must carry strongly-typed EventArgs that inherit from RoutedEventArgs so the routing infrastructure can dispatch and cast them safely. Passing a non-derived Type (e.g. plain EventArgs, or a custom class that forgot the base) violates that contract at registration time.

Source

Thrown at src/Avalonia.Base/Interactivity/RoutedEvent.cs:31

    public class RoutedEvent
    {
        private readonly LightweightSubject<(object, RoutedEventArgs)> _raised = new();
        private readonly LightweightSubject<RoutedEventArgs> _routeFinished = new();

        public RoutedEvent(
            string name,
            RoutingStrategies routingStrategies,
            Type eventArgsType,
            Type ownerType)
        {
            name = name ?? throw new ArgumentNullException(nameof(name));
            eventArgsType = eventArgsType ?? throw new ArgumentNullException(nameof(name));
            ownerType = ownerType ?? throw new ArgumentNullException(nameof(name));

            if (!typeof(RoutedEventArgs).IsAssignableFrom(eventArgsType))
            {
                throw new InvalidCastException("eventArgsType must be derived from RoutedEventArgs.");
            }

            EventArgsType = eventArgsType;
            Name = name;
            OwnerType = ownerType;
            RoutingStrategies = routingStrategies;
        }

        public Type EventArgsType { get; }

        public string Name { get; }

        public Type OwnerType { get; }

        public RoutingStrategies RoutingStrategies { get; }

        public bool HasRaisedSubscriptions => _raised.HasObservers;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Change the eventArgsType to a class that derives from RoutedEventArgs (create a custom subclass if needed).
  2. If using RoutedEvent.Register<TEventArgs>(...), ensure TEventArgs : RoutedEventArgs.
  3. Verify the Type at the call site with typeof(RoutedEventArgs).IsAssignableFrom(eventArgsType) before registration.

Example fix

// before
var evt = new RoutedEvent("Tap", RoutingStrategies.Bubble, typeof(EventArgs), typeof(MyControl));

// after
public class TapEventArgs : RoutedEventArgs { /* ... */ }
var evt = new RoutedEvent("Tap", RoutingStrategies.Bubble, typeof(TapEventArgs), typeof(MyControl));
Defensive patterns

Strategy: type-guard

Validate before calling

static bool IsRoutedEventArgsArgs(Type t) => typeof(RoutedEventArgs).IsAssignableFrom(t);

// usage
if (!IsRoutedEventArgsArgs(eventArgsType))
    throw new InvalidOperationException($"{eventArgsType} must derive from RoutedEventArgs.");
var evt = new RoutedEvent(name, routingStrategies, eventArgsType, ownerType);

Type guard

// Prefer the generic registration helper which enforces the constraint at compile time:
// RoutedEvent.Register<TEventArgs>("name", RoutingStrategies.Bubble, typeof(Owner))
// where TEventArgs : RoutedEventArgs
static RoutedEvent RegisterSafe<TArgs>(string name, RoutingStrategies rs, Type owner)
    where TArgs : RoutedEventArgs
    => RoutedEvent.Register<TArgs>(name, rs, owner);

Prevention

When it happens

Trigger: Calling `new RoutedEvent(name, routingStrategies, eventArgsType, ownerType)` or the `RoutedEvent.Register(...)` helper where `eventArgsType` is a Type that is not assignable to `typeof(RoutedEventArgs)`. Also fires if reflection or a generic registration helper forwards an unconstrained Type argument.

Common situations: Creating a custom routed event for a control and accidentally passing `typeof(EventArgs)` instead of a RoutedEventArgs-derived type. Copy-pasting a RoutedEvent.Register call and forgetting to update the generic/eventArgsType argument. Using an interop/event-args class from another framework that does not inherit from Avalonia's RoutedEventArgs.

Related errors


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