{"record":{"id":"e224515e84b4caf1","repo":"emilk/egui","slug":"we-should-always-find-the-root","errorCode":null,"errorMessage":"We should always find the root","messagePattern":"We should always find the root","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/egui/src/containers/menu.rs","lineNumber":42,"sourceCode":"pub fn menu_style(style: &mut Style) {\n    style.spacing.button_padding = vec2(2.0, 0.0);\n    style.visuals.widgets.active.bg_stroke = Stroke::NONE;\n    style.visuals.widgets.open.bg_stroke = Stroke::NONE;\n    style.visuals.widgets.hovered.bg_stroke = Stroke::NONE;\n    style.visuals.widgets.inactive.weak_bg_fill = Color32::TRANSPARENT;\n    style.visuals.widgets.inactive.bg_stroke = Stroke::NONE;\n}\n\n/// Find the root [`UiStack`] of the menu.\npub fn find_menu_root(ui: &Ui) -> &UiStack {\n    ui.stack()\n        .iter()\n        .find(|stack| {\n            stack.is_root_ui()\n                || [Some(UiKind::Popup), Some(UiKind::Menu)].contains(&stack.kind())\n                || stack.info.tags.contains(MenuConfig::MENU_CONFIG_TAG)\n        })\n        .expect(\"We should always find the root\")\n}\n\n/// Is this Ui part of a menu?\n///\n/// Returns `false` if this is a menu bar.\n/// Should be used to determine if we should show a menu button or submenu button.\npub fn is_in_menu(ui: &Ui) -> bool {\n    for stack in ui.stack().iter() {\n        if let Some(config) = stack\n            .info\n            .tags\n            .get_downcast::<MenuConfig>(MenuConfig::MENU_CONFIG_TAG)\n        {\n            return !config.bar;\n        }\n        if [Some(UiKind::Popup), Some(UiKind::Menu)].contains(&stack.kind()) {\n            return true;\n        }","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/emilk/egui/blob/8fb03c9ae9a6bf1ffa602dfba51ed575f2655975/crates/egui/src/containers/menu.rs#L24-L60","documentation":"egui's find_menu_root walks the Ui stack to locate the root of a menu/popup hierarchy and expects at least one ancestor to be a root Ui, a Popup/Menu, or carry the MenuConfig tag. The panic fires when a menu-related query is issued from a Ui whose ancestor stack contains no such root, meaning the code ran outside any initialized menu/popup context. It is an internal invariant of the menu system: every Ui used with menu APIs must descend from a menu root.","triggerScenarios":"Calling menu APIs (find/find_menu_root/from_ui) on a Ui created outside a Context::run/BeginPass frame, or on a Ui detached from any window/area whose stack is not marked as root, popup, menu, or tagged with MenuConfig::MENU_CONFIG_TAG.","commonSituations":"Showing a context menu during a custom repaint outside egui's frame loop; using a Ui captured from a previous frame; building menus in a deferred/threads context where the Ui stack was never pushed; version changes where the root-detection predicate became stricter.","solutions":["Ensure menu code runs inside a normal egui pass (inside Context::run / the eframe update callback) with a valid Ui from ctx or a window","If using a custom Ui, wrap it in an area/window so a root Ui exists in the stack, or tag it with MenuConfig::MENU_CONFIG_TAG","Verify the Ui passed to menu APIs was not captured from an earlier frame or created before any pass started","Check for upgrade changes to crates/egui/src/containers/menu.rs root detection and adapt code to the new MenuConfig API"],"exampleFix":"// before\nlet menu_root = MenuConfig::default().find(ui); // ui captured from a previous frame\n// after\nctx.run(ctx.input(|i| i.time), |ctx| {\n    let ui = &mut egui::CentralPanel::default().show(ctx, |ui| {\n        MenuConfig::default().find(ui)\n    }).inner;\n});","handlingStrategy":"type-guard","validationCode":"// Rust: only query menu state from a live pass Ui\nif ctx.is_using_pointer() && std::ptr::eq(ui.ctx(), &ctx) {\n    let root = MenuConfig::default().find(ui);\n}","typeGuard":"fn has_menu_root(ui: &egui::Ui) -> bool {\n    ui.ctx().find_menu_root_checked().is_some()\n}","tryCatchPattern":null,"preventionTips":["Never reuse Ui objects from previous frames","Run all menu code inside Context::run / eframe update","Tag custom containers with MenuConfig::MENU_CONFIG_TAG when they host menus","Keep egui integration code inside the standard frame loop"],"tags":["egui","ui","menu","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8fb03c9ae9a6bf1ffa602dfba51ed575f2655975","analyzedAt":"2026-09-12T04:29:21.500Z","contentChangedAt":"2026-09-12T04:29:21.500Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}