stride3d/stride · error · ArgumentNullException

Value cannot be null. (Parameter 'handler')

Error message

Value cannot be null. (Parameter 'handler')

What it means

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.

Solutions

  1. Check the handler argument at the call site for null before calling RegisterValueChangedHandler.
  2. If the handler is created via reflection, verify Delegate.CreateDelegate returned non-null and that the method signature matches EventHandler(object, EventArgs).
  3. Ensure the callback field/property is initialized before watcher registration; defer AttachHandlers until assignment is complete.
  4. Use a no-op fallback handler if a null handler is semantically acceptable, rather than passing null.

Example fix

// before
EventHandler handler = null;
watcher.RegisterValueChangedHandler(prop, handler);
// after
EventHandler handler = OnWidthChanged;
if (handler == null) handler = (s, e) => { };
watcher.RegisterValueChangedHandler(prop, handler);
Defensive patterns

Strategy: type-guard

Validate before calling

if (handler == null) throw new InvalidOperationException("Value-changed handler must be assigned before registration.");

Type guard

static bool IsValidHandler(EventHandler h) => h is not null;

Try / catch

try { watcher.RegisterValueChangedHandler(prop, handler); }
catch (ArgumentNullException ex) when (ex.ParamName == "handler") { log.Warn("Null handler passed to watcher"); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/bc21252a4e16ebe0. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Core/DependencyPropertyWatcher.cs:104

            }
        }

        private void DetachHandlers()
        {
            if (handlerRegistered)
            {
                foreach (var handler in handlers)
                {
                    DetachHandler(handler.Item1, handler.Item2);
                }
                handlerRegistered = false;
            }
        }

        private void AttachHandler([NotNull] DependencyProperty property, [NotNull] EventHandler handler)
        {
            if (property == null) throw new ArgumentNullException(nameof(property));
            if (handler == null) throw new ArgumentNullException(nameof(handler));
            if (frameworkElement == null) throw new InvalidOperationException("A dependency object must be attached in order to register a handler.");

            DependencyPropertyDescriptor descriptor;
            if (!descriptors.TryGetValue(property, out descriptor))
            {
                descriptor = DependencyPropertyDescriptor.FromProperty(property, AssociatedObject.GetType());
                descriptors.Add(property, descriptor);
            }
            descriptor.AddValueChanged(AssociatedObject, handler);
        }

        private void DetachHandler([NotNull] DependencyProperty property, [NotNull] EventHandler handler)
        {
            if (property == null) throw new ArgumentNullException(nameof(property));
            if (handler == null) throw new ArgumentNullException(nameof(handler));
            if (frameworkElement == null) throw new InvalidOperationException("A dependency object must be attached in order to unregister a handler.");

            DependencyPropertyDescriptor descriptor;

View on GitHub (pinned to 96fad776d2)