{"record":{"id":"6b5d32fb84aec745","repo":"stride3d/stride","slug":"value-cannot-be-null-parameter-handler","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'handler')","messagePattern":"Value cannot be null\\. \\(Parameter 'handler'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.UI/Events/EventManager.cs","lineNumber":79,"sourceCode":"            }\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>\n        internal static RoutedEventHandlerInfo GetClassHandler(Type classType, RoutedEvent routedEvent)","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.UI/Events/EventManager.cs#L61-L97","documentation":"EventManager.RegisterClassHandler<T> requires a non-null handler delegate; class handlers are stored as RoutedEventHandlerInfo and invoked during routing, so a null handler is invalid. Fail-fast ArgumentNullException thrown before any state is mutated.","triggerScenarios":"Calling EventManager.RegisterClassHandler<T>(classType, routedEvent, null), e.g. when the handler method reference is resolved via reflection and the method is missing, or a variable holding the delegate was never assigned.","commonSituations":"Renaming or deleting a handler method while a registration still references it; reflection-based lookup returning null; conditional code paths that leave the delegate unassigned.","solutions":["Pass a valid EventHandler<T> delegate; verify the handler method exists and matches the generic RoutedEventArgs subtype","If the handler is resolved dynamically, null-check before registering and log/skip otherwise","Remove the registration call entirely if the handler no longer exists"],"exampleFix":"// before\nEventHandler<RoutedEventArgs> h = ResolveHandler(); // may be null\nEventManager.RegisterClassHandler(typeof(Button), Button.ClickEvent, h);\n// after\nvar h = ResolveHandler() ?? throw new InvalidOperationException(\"Click handler missing\");\nEventManager.RegisterClassHandler(typeof(Button), Button.ClickEvent, h);","handlingStrategy":"validation","validationCode":"if (handler == null) throw new InvalidOperationException(\"RegisterClassHandler requires a non-null handler\");","typeGuard":"static bool HasHandler<T>(EventHandler<T> h) where T : RoutedEventArgs => h != null;","tryCatchPattern":"try { EventManager.RegisterClassHandler<T>(classType, evt, handler); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"handler\") { logger.LogWarning(\"Skipping class handler registration: handler was null\"); }","preventionTips":["Reference handler methods directly instead of via reflection","Keep handler method signatures aligned with the generic RoutedEventArgs subtype","Delete registrations when removing handler methods"],"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"}