{"record":{"id":"022119a4fbf86a86","repo":"elkowar/eww","slug":"this-child-already-has-a-parent","errorCode":null,"errorMessage":"this child already has a parent","messagePattern":"this child already has a parent","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/eww/src/state/one_to_n_elements_map.rs","lineNumber":23,"sourceCode":"#[derive(Debug)]\npub struct OneToNElementsMap<I, T> {\n    pub(super) child_to_parent: HashMap<I, (I, T)>,\n    pub(super) parent_to_children: HashMap<I, HashSet<I>>,\n}\n\nimpl<I: Copy + std::hash::Hash + std::cmp::Eq + std::fmt::Debug, T> OneToNElementsMap<I, T> {\n    pub fn new() -> Self {\n        OneToNElementsMap { child_to_parent: HashMap::new(), parent_to_children: HashMap::new() }\n    }\n\n    pub fn clear(&mut self) {\n        self.child_to_parent.clear();\n        self.parent_to_children.clear()\n    }\n\n    pub fn insert(&mut self, child: I, parent: I, edge: T) -> Result<()> {\n        if self.child_to_parent.contains_key(&child) {\n            bail!(\"this child already has a parent\");\n        }\n        self.child_to_parent.insert(child, (parent, edge));\n        self.parent_to_children.entry(parent).or_default().insert(child);\n        Ok(())\n    }\n\n    pub fn remove(&mut self, scope: I) {\n        if let Some(children) = self.parent_to_children.remove(&scope) {\n            for child in &children {\n                self.child_to_parent.remove(child);\n            }\n        }\n        if let Some((parent, _)) = self.child_to_parent.remove(&scope) {\n            if let Some(children_of_parent) = self.parent_to_children.get_mut(&parent) {\n                children_of_parent.remove(&scope);\n            }\n        }\n    }","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/elkowar/eww/blob/48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa/crates/eww/src/state/one_to_n_elements_map.rs#L5-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove the child's existing mapping before re-inserting (add a remove/delete API call)","Clear the map (clear()) before rebuilding the whole structure on reload","Ensure widget ids/indices are unique so the same child is not inserted twice","Fix duplicate window/widget definitions in the yuck config"],"exampleFix":"// before\nmap.insert(child, parent, edge)?;\nmap.insert(child, other_parent, edge)?; // panics: already has a parent\n// after\nmap.remove(&child); // or: if map.parent_of(&child) != Some(&parent) { map.remove(&child); }\nmap.insert(child, other_parent, edge)?;","handlingStrategy":"validation","validationCode":"if (map.getParent(child) !== undefined) {\n  throw new Error(`child ${child} already has parent ${map.getParent(child)}`);\n}","typeGuard":"function canInsert(map, child) { return map.getParent(child) === undefined; }","tryCatchPattern":"match map.insert(child, parent, edge) {\n    Ok(()) => {},\n    Err(_) => { map.remove(&child); map.insert(child, parent, edge)?; }\n}","preventionTips":["Remove existing mappings before re-inserting a child","Clear the map when rebuilding structures on reload","Guarantee unique child ids in widget/state graphs","Fix duplicate widget definitions in yuck"],"tags":["data-structure","invariant","state"],"backgroundTag":"internal-invariant-violation","analyzedSha":"48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa","analyzedAt":"2026-09-08T03:13:26.897Z","contentChangedAt":"2026-09-08T03:13:26.897Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}