stride3d/stride · error · ArgumentNullException

Value cannot be null. (Parameter 'property')

Error message

Value cannot be null. (Parameter 'property')

What it means

DependencyPropertyWatcher.AttachHandler validates that the DependencyProperty passed to it is not null and throws ArgumentNullException(nameof(property)) when it is. The watcher registers change handlers for dependency properties, and a null property cannot be mapped to a DependencyPropertyDescriptor. The library throws immediately to fail fast rather than crashing later inside the descriptor cache.

Solutions

  1. Verify the DependencyProperty value passed to RegisterValueChangedHandler is non-null before calling the watcher; assert or log it at the call site.
  2. If the property is looked up by name (DependencyProperty.FromName / reflection), check that the owner type and assembly match and that the property still exists.
  3. Ensure the static DependencyProperty field on the owner class is initialized (correct static constructor, no field renamed/deleted).
  4. Wrap the registration in a null check and skip with a clear diagnostic instead of letting the ArgumentNullException surface from deep inside the watcher.

Example fix

// before
watcher.RegisterValueChangedHandler(FindProperty("Width"), OnWidthChanged);
// after
var prop = FindProperty("Width");
if (prop == null) throw new InvalidOperationException("Dependency property 'Width' not found on owner type.");
watcher.RegisterValueChangedHandler(prop, OnWidthChanged);
Defensive patterns

Strategy: type-guard

Validate before calling

if (property == null) throw new InvalidOperationException("Dependency property must be resolved before registering a watcher handler.");

Type guard

static bool IsValidDependencyProperty(DependencyProperty p) => p is not null;

Try / catch

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

Prevention

When it happens

Trigger: Calling RegisterValueChangedHandler (or AttachHandlers, which enumerates watched properties) with a null DependencyProperty reference — typically because a static DependencyProperty field was null at lookup time, a dictionary/dictionary-of-properties lookup missed and returned null, or a property metadata lookup (e.g. DependencyProperty.FromName or a Find-by-name reflection call) failed silently and its null result was forwarded.

Common situations: XAML/BAML binding to a dependency property whose owner type or property name was renamed or moved to another assembly; reflection-based registration where typeof checks were skipped; refactoring that renamed a static DependencyProperty field while a watcher still references the old name; code running before static initializers of the owner type completed.

Related errors


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

Appendix: source

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

                handlerRegistered = true;
            }
        }

        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.");

View on GitHub (pinned to 96fad776d2)