stride3d/stride · error · InvalidOperationException

The routed event cannot be changed while the event is being…

Error message

The routed event cannot be changed while the event is being routed.

What it means

RoutedEventArgs.RoutedEvent setter throws InvalidOperationException if the arguments are currently being routed (IsBeingRouted is true). The routing engine relies on the event identity staying stable while it walks the element tree, so mutating it mid-route would corrupt the routing pass.

Solutions

  1. Raise a new event with a fresh RoutedEventArgs instance instead of mutating the in-flight one
  2. Defer the change until after routing completes (e.g. Dispatcher.InvokeAsync)
  3. If you need different event data, create a new RoutedEventArgs subclass instance per RaiseEvent call

Example fix

// before
void OnTap(object sender, RoutedEventArgs e)
{
    e.RoutedEvent = DoubleTapEvent; // throws while routing
    element.RaiseEvent(e);
}
// after
void OnTap(object sender, RoutedEventArgs e)
{
    var newArgs = new RoutedEventArgs(DoubleTapEvent) { Source = element };
    element.RaiseEvent(newArgs);
}
Defensive patterns

Strategy: validation

Validate before calling

if (args.IsBeingRouted) throw new InvalidOperationException("Cannot change RoutedEvent while routing");

Type guard

static bool CanMutate(RoutedEventArgs args) => args != null && !args.IsBeingRouted;

Try / catch

try { args.RoutedEvent = newEvent; }
catch (InvalidOperationException) { var fresh = new RoutedEventArgs(newEvent) { Source = args.Source }; target.RaiseEvent(fresh); }

Prevention

When it happens

Trigger: Assigning args.RoutedEvent = someEvent from inside a routed-event handler or from code running during RaiseEvent, while the same RoutedEventArgs instance is in flight.

Common situations: Handler code that tries to 'retarget' the event to another RoutedEvent; framework/library callbacks invoked during routing that reuse the same args object; helper methods called synchronously from handlers.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/7d3c80ab838fba26. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.UI/Events/RoutedEventArgs.cs:33

        public bool Handled { get; set; }

        private RoutedEvent routedEvent;

        private UIElement source;

        protected bool IsBeingRouted { get; private set; }

        /// <summary>
        /// Gets or sets the <see cref="RoutedEvent"/> associated with this RoutedEventArgs instance.
        /// </summary>
        /// <exception cref="InvalidOperationException">Attempted to change the RoutedEvent value while the event is being routed.</exception>
        public RoutedEvent RoutedEvent 
        {
            get { return routedEvent; }
            set
            {
                if (IsBeingRouted)
                    throw new InvalidOperationException("The routed event cannot be changed while the event is being routed.");

                routedEvent = value;
            }
        }

        /// <summary>
        /// Gets or sets a reference to the object that raised the event.
        /// </summary>
        /// <exception cref="InvalidOperationException">Attempted to change the source value while the event is being routed.</exception>
        public UIElement Source 
        {
            get { return source; }
            set
            {
                if (IsBeingRouted)
                    throw new InvalidOperationException("The routed event cannot be changed while the event is being routed.");

                source = value;

View on GitHub (pinned to 96fad776d2)