leptos-rs/leptos · error

anchor is not a child of the parent

Error message

anchor is not a child of the parent

What it means

MockRenderer::insert_node inserts a child before an anchor by finding the anchor's position in the parent's children list; if the anchor is not among the parent's children, position() returns None and it panics. The mock DOM mirrors real renderer invariants, so this flags bookkeeping drift between parent/anchor tracking.

Source

Thrown at tachys/src/renderer/mock_dom.rs:493

        debug_assert!(&parent.0 != new_child);
        // remove if already mounted
        if let Some(parent) = MockDom::get_parent(new_child) {
            let parent = Element(parent);
            MockDom::remove_node(&parent, new_child);
        }
        // mount on new parent
        Document::with_node_mut(parent.0 .0, |parent| {
            if let NodeType::Element {
                ref mut children, ..
            } = parent.ty
            {
                match anchor {
                    None => children.push(new_child.clone()),
                    Some(anchor) => {
                        let anchor_pos = children
                            .iter()
                            .position(|item| item.0 == anchor.0)
                            .expect("anchor is not a child of the parent");
                        children.insert(anchor_pos, new_child.clone());
                    }
                }
            } else {
                panic!("parent is not an element");
            }
        });
        // set parent on child node
        Document::with_node_mut(new_child.0, |node| {
            node.parent = Some(parent.0 .0)
        });
    }

    fn remove_node(
        parent: &Self::Element,
        child: &Self::Node,
    ) -> Option<Self::Node> {
        let child = Document::with_node_mut(parent.0 .0, |parent| {

View on GitHub (pinned to 32d20f6c9d)

Solutions

  1. Ensure the anchor passed to insert_node is a current child of the same parent node
  2. Update anchors after moving/removing nodes in the mock DOM before re-inserting
  3. Re-render or rebuild the mock tree when structural tests mutate children directly
  4. If testing reconciliation, use the renderer's own move/remove APIs instead of poking the children vec

Example fix

// before
mock.insert_node(&mut node, &stale_anchor); // panics
// after
assert!(parent.children().any(|c| c == stale_anchor));
mock.insert_node(&mut node, &stale_anchor); // anchor verified in parent
Defensive patterns

Strategy: validation

Validate before calling

fn is_child(parent: &MockNode, anchor: &MockNode) -> bool {
    parent.children().iter().any(|c| c.id == anchor.id)
}
// call before: assert!(is_child(&parent, &anchor));

Type guard

fn find_anchor_pos(children: &[MockNode], anchor: &MockNode) -> Option<usize> {
    children.iter().position(|c| c.id == anchor.id)
}

Prevention

When it happens

Trigger: Calling insert_node with an anchor belonging to a different parent, an anchor already removed from the mock DOM, or stale anchor references after mock-DOM mutations; also implicitly when parent bookkeeping (children vec) diverges from anchor references.

Common situations: Unit/integration tests using the mock DOM renderer with manually manipulated children; view reconciliation code paths that move anchors without updating the parent's child list; cloning anchors across trees in tests.

Related errors


AI-assisted analysis of leptos-rs/leptos@32d20f6c9d (2026-09-01). Data as JSON: /api/errors/6e038c71d9365c31. Report an issue: GitHub.