{"record":{"id":"06d9e4d34a301eec","repo":"stride3d/stride","slug":"value-cannot-be-null-parameter-routedevent","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'routedEvent')","messagePattern":"Value cannot be null\\. \\(Parameter 'routedEvent'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.UI/Events/EventManager.cs","lineNumber":78,"sourceCode":"                currentType = currentType.GetTypeInfo().BaseType;\n            }\n\n            return types.Where(t => OwnerToEvents.ContainsKey(t)).SelectMany(t => OwnerToEvents[t].Values).ToArray();\n        }\n\n        /// <summary>\n        /// Registers a class handler for a particular routed event, with the option to handle events where event data is already marked handled.\n        /// </summary>\n        /// <param name=\"classType\">The type of the class that is declaring class handling.</param>\n        /// <param name=\"routedEvent\">The routed event identifier of the event to handle.</param>\n        /// <param name=\"handler\">A reference to the class handler implementation.</param>\n        /// <param name=\"handledEventsToo\">true to invoke this class handler even if arguments of the routed event have been marked as handled; \n        /// false to retain the default behavior of not invoking the handler on any marked-handled event.</param>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"classType\"/>, <paramref name=\"routedEvent\"/>, or <paramref name=\"handler\"/> is null.</exception>\n        public static void RegisterClassHandler<T>(Type classType, RoutedEvent<T> routedEvent, EventHandler<T> handler, bool handledEventsToo = false) where T : RoutedEventArgs\n        {\n            if (classType == null) throw new ArgumentNullException(nameof(classType));\n            if (routedEvent == null) throw new ArgumentNullException(nameof(routedEvent));\n            if (handler == null) throw new ArgumentNullException(nameof(handler));\n\n            lock(SyncRoot)\n            {\n                if (!ClassesToClassHandlers.ContainsKey(classType))\n                    ClassesToClassHandlers[classType] = new Dictionary<RoutedEvent, RoutedEventHandlerInfo>();\n\n                ClassesToClassHandlers[classType][routedEvent] = new RoutedEventHandlerInfo<T>(handler, handledEventsToo); \n            }\n        }\n\n        /// <summary>\n        /// Get the class handler for the class <paramref name=\"classType\"/> and routed event <paramref name=\"routedEvent\"/>.\n        /// </summary>\n        /// <param name=\"classType\">The type of the class that is handling the event.</param>\n        /// <param name=\"routedEvent\">The routed event to handle</param>\n        /// <returns>The class handler</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"classType\"/>, or <paramref name=\"routedEvent\"/> is null.</exception>","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.UI/Events/EventManager.cs#L60-L96","documentation":"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>.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nEventManager.RegisterClassHandler<UIElement>(typeof(UIElement), null, OnMouseMove);\n// after\nvar evt = EventManager.GetRoutedEvent<MouseButtonEventArgs>(typeof(UIElement), \"MouseDown\");\nif (evt != null)\n    EventManager.RegisterClassHandler<UIElement>(typeof(UIElement), evt, OnMouseMove);","handlingStrategy":"validation","validationCode":"if (routedEvent == null) throw new InvalidOperationException(\"RegisterClassHandler requires a non-null RoutedEvent\");","typeGuard":"static bool IsValidRoutedEvent<T>(RoutedEvent<T> evt) where T : RoutedEventArgs => evt != null;","tryCatchPattern":"try { EventManager.RegisterClassHandler<T>(classType, routedEvent, handler); }\ncatch (ArgumentNullException ex) { logger.LogError(ex, \"Class handler registration failed: {Param}\", ex.ParamName); }","preventionTips":["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"],"tags":["csharp","null-argument","ui","events"],"backgroundTag":"null-argument","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}