{"record":{"id":"bc21252a4e16ebe0","repo":"stride3d/stride","slug":"value-cannot-be-null-parameter-handler-bc2125","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/presentation/Stride.Core.Presentation.Wpf/Core/DependencyPropertyWatcher.cs","lineNumber":104,"sourceCode":"            }\n        }\n\n        private void DetachHandlers()\n        {\n            if (handlerRegistered)\n            {\n                foreach (var handler in handlers)\n                {\n                    DetachHandler(handler.Item1, handler.Item2);\n                }\n                handlerRegistered = false;\n            }\n        }\n\n        private void AttachHandler([NotNull] DependencyProperty property, [NotNull] EventHandler handler)\n        {\n            if (property == null) throw new ArgumentNullException(nameof(property));\n            if (handler == null) throw new ArgumentNullException(nameof(handler));\n            if (frameworkElement == null) throw new InvalidOperationException(\"A dependency object must be attached in order to register a handler.\");\n\n            DependencyPropertyDescriptor descriptor;\n            if (!descriptors.TryGetValue(property, out descriptor))\n            {\n                descriptor = DependencyPropertyDescriptor.FromProperty(property, AssociatedObject.GetType());\n                descriptors.Add(property, descriptor);\n            }\n            descriptor.AddValueChanged(AssociatedObject, handler);\n        }\n\n        private void DetachHandler([NotNull] DependencyProperty property, [NotNull] EventHandler handler)\n        {\n            if (property == null) throw new ArgumentNullException(nameof(property));\n            if (handler == null) throw new ArgumentNullException(nameof(handler));\n            if (frameworkElement == null) throw new InvalidOperationException(\"A dependency object must be attached in order to unregister a handler.\");\n\n            DependencyPropertyDescriptor descriptor;","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Wpf/Core/DependencyPropertyWatcher.cs#L86-L122","documentation":"DependencyPropertyWatcher.AttachHandler validates the EventHandler argument and throws ArgumentNullException(nameof(handler)) when it is null. A null handler cannot be registered with DependencyPropertyDescriptor.AddValueChanged, so the library fails fast. Callers are RegisterValueChangedHandler and AttachHandlers.","triggerScenarios":"Passing a null delegate to RegisterValueChangedHandler — e.g. an event-handler field that was never assigned, a method group that failed to bind because of a signature mismatch resolved to null via reflection (Delegate.CreateDelegate returning null), or a conditional/reference that is null on first run.","commonSituations":"Reflection-based wiring of handlers where CreateDelegate failed silently; MVVM frameworks constructing watchers before assigning the callback; refactoring that changed the handler signature so the method-group conversion no longer compiles into a valid EventHandler; deserialized or partially initialized view models with null callbacks.","solutions":["Check the handler argument at the call site for null before calling RegisterValueChangedHandler.","If the handler is created via reflection, verify Delegate.CreateDelegate returned non-null and that the method signature matches EventHandler(object, EventArgs).","Ensure the callback field/property is initialized before watcher registration; defer AttachHandlers until assignment is complete.","Use a no-op fallback handler if a null handler is semantically acceptable, rather than passing null."],"exampleFix":"// before\nEventHandler handler = null;\nwatcher.RegisterValueChangedHandler(prop, handler);\n// after\nEventHandler handler = OnWidthChanged;\nif (handler == null) handler = (s, e) => { };\nwatcher.RegisterValueChangedHandler(prop, handler);","handlingStrategy":"type-guard","validationCode":"if (handler == null) throw new InvalidOperationException(\"Value-changed handler must be assigned before registration.\");","typeGuard":"static bool IsValidHandler(EventHandler h) => h is not null;","tryCatchPattern":"try { watcher.RegisterValueChangedHandler(prop, handler); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"handler\") { log.Warn(\"Null handler passed to watcher\"); }","preventionTips":["Store handler delegates in readonly fields.","Avoid reflection-based delegate creation; prefer method groups.","Assign callbacks before constructing/attaching the watcher.","Treat missing callbacks as no-op handlers instead of null."],"tags":["wpf","argument-null","event-handler"],"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"}