stride3d/stride · error · InvalidOperationException
A dependency object is already attached to this instance of…
Error message
A dependency object is already attached to this instance of DependencyPropertyWatcher.
What it means
DependencyPropertyWatcher.Attach can hold exactly one dependency object at a time. Calling Attach on a watcher that already has a frameworkElement attached throws InvalidOperationException, since attaching another object would lose the Loaded/Unloaded subscriptions and change handlers of the previous target.
Solutions
- Create a new DependencyPropertyWatcher instance for each dependency object.
- Detach or dispose the existing watcher (remove handlers / null out frameworkElement) before attaching a new object.
- Keep one watcher per view instead of storing watchers in shared/static state.
Example fix
// before watcher.Attach(oldElement); watcher.Attach(newElement); // throws // after watcher = new DependencyPropertyWatcher(path, onChanged); watcher.Attach(newElement);
Defensive patterns
Strategy: validation
Validate before calling
if (watcher != null && watcher.IsAttached)
watcher = new DependencyPropertyWatcher(path, onChanged);
watcher.Attach(dependencyObject); Type guard
bool CanAttach(DependencyPropertyWatcher w) => w == null || !w.IsAttached;
Try / catch
try { watcher.Attach(dependencyObject); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already attached")) { watcher = new DependencyPropertyWatcher(path, onChanged); watcher.Attach(dependencyObject); } Prevention
- Keep one watcher instance per target object; create rather than reuse.
- Release watchers on view unload (Unloaded/Dispose) instead of re-attaching.
- Avoid storing watchers in static or shared fields used by multiple views.
When it happens
Trigger: Calling watcher.Attach(dependencyObject) twice on the same watcher instance with different (or any) dependency objects while frameworkElement is already non-null and the new object is not the same reference.
Common situations: Reusing a single watcher across pages/controls without detaching; subscribing the watcher in a constructor that runs again after re-templating; holding watchers in static fields shared by multiple views.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- The dependency object to attach to the…
- A dependency object must be attached in order to register a…
- A dependency object must be attached in order to unregister…
- An instance of WindowManager is already existing.
- Trying to dispose a lock that has already been released.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/8090c5f4c8056b70.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Core/DependencyPropertyWatcher.cs:39
public DependencyPropertyWatcher()
{
}
public DependencyPropertyWatcher([NotNull] FrameworkElement attachTo)
{
Attach(attachTo);
}
public DependencyObject AssociatedObject => frameworkElement;
public void Attach([NotNull] DependencyObject dependencyObject)
{
if (dependencyObject == null) throw new ArgumentNullException(nameof(dependencyObject));
if (ReferenceEquals(dependencyObject, frameworkElement))
return;
if (frameworkElement != null)
throw new InvalidOperationException("A dependency object is already attached to this instance of DependencyPropertyWatcher.");
frameworkElement = dependencyObject as FrameworkElement;
if (frameworkElement == null)
throw new ArgumentException("The dependency object to attach to the DependencyPropertyWatcher must be a FrameworkElement.");
frameworkElement.Loaded += ElementLoaded;
frameworkElement.Unloaded += ElementUnloaded;
AttachHandlers();
}
public void Detach()
{
frameworkElement.Loaded -= ElementLoaded;
frameworkElement.Unloaded -= ElementUnloaded;
DetachHandlers();
handlers.Clear();
frameworkElement = null;
}View on GitHub (pinned to 96fad776d2)