stride3d/stride · error · ArgumentNullException
Value cannot be null. (Parameter 'routedEvent')
Error message
Value cannot be null. (Parameter 'routedEvent')
What it means
Stride's UI EventManager refuses to register a class handler when the routedEvent parameter is null. Class handlers are stored in a dictionary keyed by RoutedEvent, so a null event has no meaning and would corrupt the routing tables. This is a fail-fast guard in RegisterClassHandler<T>.
Solutions
- Ensure the RoutedEvent<T> instance is created via EventManager.RegisterRoutedEvent in a static field/ctor that runs before RegisterClassHandler is called
- If obtaining the event via GetRoutedEvent, check the result for null before passing it and fix the name/ownerType if null
- Pass the strongly-typed static field (e.g. UIElement.MouseMoveEvent) instead of a nullable local
Example fix
// before
EventManager.RegisterClassHandler<UIElement>(typeof(UIElement), null, OnMouseMove);
// after
var evt = EventManager.GetRoutedEvent<MouseButtonEventArgs>(typeof(UIElement), "MouseDown");
if (evt != null)
EventManager.RegisterClassHandler<UIElement>(typeof(UIElement), evt, OnMouseMove); Defensive patterns
Strategy: validation
Validate before calling
if (routedEvent == null) throw new InvalidOperationException("RegisterClassHandler requires a non-null RoutedEvent"); Type guard
static bool IsValidRoutedEvent<T>(RoutedEvent<T> evt) where T : RoutedEventArgs => evt != null;
Try / catch
try { EventManager.RegisterClassHandler<T>(classType, routedEvent, handler); }
catch (ArgumentNullException ex) { logger.LogError(ex, "Class handler registration failed: {Param}", ex.ParamName); } Prevention
- Declare routed events as static readonly fields initialized at type load
- Never pass the result of GetRoutedEvent without a null check
- Register class handlers once in static constructors, not per-instance code
When it happens
Trigger: Calling EventManager.RegisterClassHandler<T>(classType, routedEvent, handler) with a null routedEvent argument, typically because a static RoutedEvent field was not yet initialized or a GetRoutedEvent lookup returned null.
Common situations: Static initialization order problems where the handler registration runs before the RoutedEvent<T> static field is assigned; renaming an event so a lookup like EventManager.GetRoutedEvent returns null; copy-pasted registration code with a placeholder null.
Related errors
- Value cannot be null. (Parameter 'handler')
- Value cannot be null. (Parameter 'name')
- Value cannot be null. (Parameter 'ownerType')
- A routed event named
- The routed event cannot be changed while the event is being…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/06d9e4d34a301eec.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.UI/Events/EventManager.cs:78
currentType = currentType.GetTypeInfo().BaseType;
}
return types.Where(t => OwnerToEvents.ContainsKey(t)).SelectMany(t => OwnerToEvents[t].Values).ToArray();
}
/// <summary>
/// Registers a class handler for a particular routed event, with the option to handle events where event data is already marked handled.
/// </summary>
/// <param name="classType">The type of the class that is declaring class handling.</param>
/// <param name="routedEvent">The routed event identifier of the event to handle.</param>
/// <param name="handler">A reference to the class handler implementation.</param>
/// <param name="handledEventsToo">true to invoke this class handler even if arguments of the routed event have been marked as handled;
/// false to retain the default behavior of not invoking the handler on any marked-handled event.</param>
/// <exception cref="ArgumentNullException"><paramref name="classType"/>, <paramref name="routedEvent"/>, or <paramref name="handler"/> is null.</exception>
public static void RegisterClassHandler<T>(Type classType, RoutedEvent<T> routedEvent, EventHandler<T> handler, bool handledEventsToo = false) where T : RoutedEventArgs
{
if (classType == null) throw new ArgumentNullException(nameof(classType));
if (routedEvent == null) throw new ArgumentNullException(nameof(routedEvent));
if (handler == null) throw new ArgumentNullException(nameof(handler));
lock(SyncRoot)
{
if (!ClassesToClassHandlers.ContainsKey(classType))
ClassesToClassHandlers[classType] = new Dictionary<RoutedEvent, RoutedEventHandlerInfo>();
ClassesToClassHandlers[classType][routedEvent] = new RoutedEventHandlerInfo<T>(handler, handledEventsToo);
}
}
/// <summary>
/// Get the class handler for the class <paramref name="classType"/> and routed event <paramref name="routedEvent"/>.
/// </summary>
/// <param name="classType">The type of the class that is handling the event.</param>
/// <param name="routedEvent">The routed event to handle</param>
/// <returns>The class handler</returns>
/// <exception cref="ArgumentNullException"><paramref name="classType"/>, or <paramref name="routedEvent"/> is null.</exception>View on GitHub (pinned to 96fad776d2)