{"record":{"id":"09e804a2deb069d4","repo":"elkowar/eww","slug":"onetonelementsmap-got-into-inconsistent-state","errorCode":null,"errorMessage":"OneToNElementsMap got into inconsistent state","messagePattern":"OneToNElementsMap got into inconsistent state","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/eww/src/state/one_to_n_elements_map.rs","lineNumber":65,"sourceCode":"    pub fn get_parent_edge_of(&self, index: I) -> Option<&(I, T)> {\n        self.child_to_parent.get(&index)\n    }\n\n    pub fn get_parent_edge_mut(&mut self, index: I) -> Option<&mut (I, T)> {\n        self.child_to_parent.get_mut(&index)\n    }\n\n    #[allow(unused)]\n    pub fn get_children_of(&self, index: I) -> HashSet<I> {\n        self.parent_to_children.get(&index).cloned().unwrap_or_default()\n    }\n\n    /// Return the children and edges to those children of a given scope\n    pub fn get_children_edges_of(&self, index: I) -> Vec<(I, &T)> {\n        let mut result = Vec::new();\n        if let Some(children) = self.parent_to_children.get(&index) {\n            for child_scope in children {\n                let (_, edge) = self.child_to_parent.get(child_scope).expect(\"OneToNElementsMap got into inconsistent state\");\n                result.push((*child_scope, edge));\n            }\n        }\n        result\n    }\n\n    #[cfg_attr(not(debug_assertions), allow(dead_code))]\n    pub fn validate(&self) -> Result<()> {\n        for (parent, children) in &self.parent_to_children {\n            for child in children {\n                if let Some((parent_2, _)) = self.child_to_parent.get(child) {\n                    if parent_2 != parent {\n                        bail!(\n                            \"parent_to_child stored mapping from {:?} to {:?}, but child_to_parent contained mapping to {:?} \\\n                             instead\",\n                            parent,\n                            child,\n                            parent_2","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/elkowar/eww/blob/48f5aa8b379adf29da0b0bb9ca04164f65d8bdaa/crates/eww/src/state/one_to_n_elements_map.rs#L47-L83","documentation":"An internal invariant check in OneToNElementsMap: parent_to_children listed a child index that has no entry in child_to_parent. The two maps must always agree, so this panic indicates a corrupted internal state — a bug in the map's insert/remove logic, not bad user input.","triggerScenarios":"Calling get_children_edges_of(index) after a sequence of operations that removed a child's parent entry (or inserted the child into parent_to_children without a matching child_to_parent entry), e.g. during scope-graph rebuilds on config reload.","commonSituations":"Hit while reloading eww configs with dynamic scopes (for_each/windows), typically during rapid config reloads or hot-reload races that partially tear down scope mappings.","solutions":["Reproduce with the offending config and file a bug report with the config snippet — this is an internal invariant violation in eww's scope bookkeeping.","Work around by fully restarting the daemon (`eww kill && eww daemon`) instead of hot-reloading the dynamic config.","Update eww to the latest version in case the insert/remove inconsistency was already fixed.","Simplify the config: avoid widgets/for_each constructs that churn scope identities on every reload to reduce exposure."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// sanity-check the map before querying\nassert!(parent_to_children.keys().all(|c| child_to_parent.contains_key(c)), \"map out of sync\");","typeGuard":null,"tryCatchPattern":"// this is an unrecoverable internal invariant; catch_unwind around config reload keeps the daemon alive\nlet r = std::panic::catch_unwind(AssertUnwindSafe(|| graph.get_children_edges_of(idx)));","preventionTips":["Keep parent_to_children and child_to_parent mutations paired in a single method","Write property tests asserting the two maps mirror each other after insert/remove","Avoid rapid config reloads on broken configs until the bug is fixed","Report the triggering config upstream"],"tags":["internal-invariant","state-management","panic"],"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"}