stride3d/stride · error · InvalidOperationException

Model doesn't have expected parent.

Error message

Model doesn't have expected parent.

What it means

When a Model is removed from a Children collection, Model.Children_CollectionChangeeshanged verifies the child's parent is the collection's owner before clearing it. If child.parent does not match, the internal parent/child bookkeeping is inconsistent and InvalidOperationException is thrown.

Solutions

  1. Always add/remove children through the parent's Children collection and never set child.parent directly
  2. Ensure the child belongs to this parent before calling Remove (parent.Children.Contains(child))
  3. Re-add the child to the correct parent's collection so the bookkeeping is repaired before removing

Example fix

// before
child.parent = newParent; // breaks invariants
oldParent.Children.Remove(child); // throws
// after
oldParent.Children.Remove(child); // clears child.parent properly
newParent.Children.Add(child);
Defensive patterns

Strategy: validation

Validate before calling

if (child.parent != this) return; // nothing to remove from this parent's bookkeeping
parent.Children.Remove(child);

Type guard

static bool BelongsTo(Model child, Model owner) => child.parent == owner;

Try / catch

try { parent.Children.Remove(child); }
catch (InvalidOperationException ex) when (ex.Message == "Model doesn't have expected parent.") {
    // bookkeeping corrupted; re-add to correct parent to repair
    child.parent?.Children.Add(child);
}

Prevention

When it happens

Trigger: Removing a Model from a Children collection when its parent field points elsewhere — e.g. the child was manually re-parented, added to another collection, or its parent was changed without going through Children.

Common situations: Mixing manual parent manipulation with Children collection updates; stale removal after the child was moved; deserialization that sets parents directly then mutates collections.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/Model.cs:161

            result.Skeleton = Skeleton;
            result.BoundingBox = BoundingBox;

            return result;
        }

        private void Children_CollectionChanged(object sender, TrackingCollectionChangedEventArgs e)
        {
            var child = (Model)e.Item;
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (child.parent != null)
                        throw new InvalidOperationException("Model already have a parent.");
                    child.parent = this;
                    break;
                case NotifyCollectionChangedAction.Remove:
                    if (child.parent != this)
                        throw new InvalidOperationException("Model doesn't have expected parent.");
                    child.parent = null;
                    break;
            }
        }
    }
}

View on GitHub (pinned to 96fad776d2)