{"record":{"id":"c585ea6ea61ecc0d","repo":"stride3d/stride","slug":"value-cannot-be-null-parameter-ownertype-eventmanager","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'ownerType')","messagePattern":"Value cannot be null\\. \\(Parameter 'ownerType'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.UI/Events/EventManager.cs","lineNumber":132,"sourceCode":"\n        private static readonly Dictionary<Type, Dictionary<RoutedEvent, RoutedEventHandlerInfo>> ClassesToClassHandlers = new Dictionary<Type, Dictionary<RoutedEvent, RoutedEventHandlerInfo>>();\n\n        /// <summary>\n        /// Registers a new routed event.\n        /// </summary>\n        /// <param name=\"name\">The name of the routed event. The name must be unique within the owner type (base class included) and cannot be null or an empty string.</param>\n        /// <param name=\"routingStrategy\">The routing strategy of the event as a value of the enumeration.</param>\n        /// <param name=\"ownerType\">The owner class type of the routed event. This cannot be null.</param>\n        /// <returns>The identifier for the newly registered routed event. \n        /// This identifier object can now be stored as a static field in a class and then used as a parameter for methods that attach handlers to the event. \n        /// The routed event identifier is also used for other event system APIs.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"name\"/> or <paramref name=\"ownerType\"/> is null.</exception>\n        /// <exception cref=\"InvalidOperationException\">This exception is thrown if a routed event of name <paramref name=\"name\"/> already exists for type <paramref name=\"ownerType\"/> and parents.\n        /// </exception>\n        public static RoutedEvent<T> RegisterRoutedEvent<T>(string name, RoutingStrategy routingStrategy, Type ownerType) where T: RoutedEventArgs\n        {\n            if (name == null) throw new ArgumentNullException(nameof(name));\n            if (ownerType == null) throw new ArgumentNullException(nameof(ownerType));\n            \n            if (GetRoutedEvent(ownerType, name) != null)\n                throw new InvalidOperationException(\"A routed event named '\" + name + \"' already exists in provided owner type '\" + ownerType + \"' or base classes.\");\n\n            var newRoutedEvent = new RoutedEvent<T> {  Name = name, OwnerType = ownerType, RoutingStrategy = routingStrategy, };\n            lock(SyncRoot)\n            {\n                RoutedEvents.Add(newRoutedEvent);\n\n                if (!OwnerToEvents.ContainsKey(ownerType))\n                    OwnerToEvents[ownerType] = new Dictionary<string, RoutedEvent>();\n\n                OwnerToEvents[ownerType][name] = newRoutedEvent; \n            }\n\n            return newRoutedEvent;\n        }\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.UI/Events/EventManager.cs#L114-L150","documentation":"RegisterRoutedEvent<T> requires a non-null ownerType; the owner type scopes the event name and is used for duplicate detection and later GetRoutedEvent lookups. Null is rejected immediately with ArgumentNullException.","triggerScenarios":"Calling EventManager.RegisterRoutedEvent<T>(name, routingStrategy, null), e.g. passing typeof(...) of a generic type parameter resolved at runtime that came back null, or a Type field not yet initialized.","commonSituations":"Reflection-based Type.GetType with a bad assembly-qualified name returning null; passing a variable instead of typeof(YourControl); static initialization order issues.","solutions":["Pass typeof(YourControl) of the class that owns the event","If the type is resolved dynamically, null-check the Type before registering","Fix the type name/assembly string in Type.GetType calls"],"exampleFix":"// before\nvar owner = Type.GetType(\"MyApp.MyControl\"); // null if wrong assembly\nEventManager.RegisterRoutedEvent<RoutedEventArgs>(\"Tap\", RoutingStrategy.Bubble, owner);\n// after\nEventManager.RegisterRoutedEvent<RoutedEventArgs>(\"Tap\", RoutingStrategy.Bubble, typeof(MyApp.MyControl));","handlingStrategy":"validation","validationCode":"if (ownerType == null) throw new InvalidOperationException(\"Owner type must be provided\");","typeGuard":"static bool ValidOwnerType(Type t) => t != null && !t.IsGenericTypeDefinition;","tryCatchPattern":"try { return EventManager.RegisterRoutedEvent<T>(name, strategy, ownerType); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"ownerType\") { logger.LogError(ex, \"Owner type was null for event {Name}\", name); throw; }","preventionTips":["Always pass typeof(YourControl)","Avoid Type.GetType with hardcoded strings; prefer direct type references","Register events inside the owning class's static constructor"],"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"}