elkowar/eww · error

this child already has a parent

Error message

this child already has a parent

What it means

OneToNElementsMap enforces that each child has exactly one parent. insert() bails if the child already has a parent mapping. This protects the invariant that a child cannot be attached to two parents at once.

Solutions

  1. Remove the child's existing mapping before re-inserting (add a remove/delete API call)
  2. Clear the map (clear()) before rebuilding the whole structure on reload
  3. Ensure widget ids/indices are unique so the same child is not inserted twice
  4. Fix duplicate window/widget definitions in the yuck config

Example fix

// before
map.insert(child, parent, edge)?;
map.insert(child, other_parent, edge)?; // panics: already has a parent
// after
map.remove(&child); // or: if map.parent_of(&child) != Some(&parent) { map.remove(&child); }
map.insert(child, other_parent, edge)?;
Defensive patterns

Strategy: validation

Validate before calling

if (map.getParent(child) !== undefined) {
  throw new Error(`child ${child} already has parent ${map.getParent(child)}`);
}

Type guard

function canInsert(map, child) { return map.getParent(child) === undefined; }

Try / catch

match map.insert(child, parent, edge) {
    Ok(()) => {},
    Err(_) => { map.remove(&child); map.insert(child, parent, edge)?; }
}

Prevention

When it happens

Trigger: Calling insert(child, parent, edge) twice for the same child without first removing the existing mapping — e.g. rebuilding widget hierarchy or inheritance relations while old entries persist.

Common situations: Hot-reloading configs where widgets are re-inserted without clearing old relations; duplicate widget indices in yuck leading to the same child index inserted under two parents; reusing child ids.

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.


AI-assisted analysis of elkowar/eww@48f5aa8b37 (2026-09-08). Data as JSON: /api/errors/022119a4fbf86a86. Report an issue: GitHub.

Appendix: source

Thrown at crates/eww/src/state/one_to_n_elements_map.rs:23

#[derive(Debug)]
pub struct OneToNElementsMap<I, T> {
    pub(super) child_to_parent: HashMap<I, (I, T)>,
    pub(super) parent_to_children: HashMap<I, HashSet<I>>,
}

impl<I: Copy + std::hash::Hash + std::cmp::Eq + std::fmt::Debug, T> OneToNElementsMap<I, T> {
    pub fn new() -> Self {
        OneToNElementsMap { child_to_parent: HashMap::new(), parent_to_children: HashMap::new() }
    }

    pub fn clear(&mut self) {
        self.child_to_parent.clear();
        self.parent_to_children.clear()
    }

    pub fn insert(&mut self, child: I, parent: I, edge: T) -> Result<()> {
        if self.child_to_parent.contains_key(&child) {
            bail!("this child already has a parent");
        }
        self.child_to_parent.insert(child, (parent, edge));
        self.parent_to_children.entry(parent).or_default().insert(child);
        Ok(())
    }

    pub fn remove(&mut self, scope: I) {
        if let Some(children) = self.parent_to_children.remove(&scope) {
            for child in &children {
                self.child_to_parent.remove(child);
            }
        }
        if let Some((parent, _)) = self.child_to_parent.remove(&scope) {
            if let Some(children_of_parent) = self.parent_to_children.get_mut(&parent) {
                children_of_parent.remove(&scope);
            }
        }
    }

View on GitHub (pinned to 48f5aa8b37)