emilk/egui · error
We should always find the root
Error message
We should always find the root
What it means
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.
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
Example fix
// before
let menu_root = MenuConfig::default().find(ui); // ui captured from a previous frame
// after
ctx.run(ctx.input(|i| i.time), |ctx| {
let ui = &mut egui::CentralPanel::default().show(ctx, |ui| {
MenuConfig::default().find(ui)
}).inner;
}); Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: only query menu state from a live pass Ui
if ctx.is_using_pointer() && std::ptr::eq(ui.ctx(), &ctx) {
let root = MenuConfig::default().find(ui);
} Type guard
fn has_menu_root(ui: &egui::Ui) -> bool {
ui.ctx().find_menu_root_checked().is_some()
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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.
Related errors
- Context::root_ui was called while the root Ui was already…
- Could not create Date
- Could not create Date
- failed to get current context to resize surface
- Harness::ui_id is only available for harnesses built with a…
AI-assisted analysis of emilk/egui@8fb03c9ae9 (2026-09-12).
Data as JSON: /api/errors/e224515e84b4caf1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/egui/src/containers/menu.rs:42
pub fn menu_style(style: &mut Style) {
style.spacing.button_padding = vec2(2.0, 0.0);
style.visuals.widgets.active.bg_stroke = Stroke::NONE;
style.visuals.widgets.open.bg_stroke = Stroke::NONE;
style.visuals.widgets.hovered.bg_stroke = Stroke::NONE;
style.visuals.widgets.inactive.weak_bg_fill = Color32::TRANSPARENT;
style.visuals.widgets.inactive.bg_stroke = Stroke::NONE;
}
/// Find the root [`UiStack`] of the menu.
pub fn find_menu_root(ui: &Ui) -> &UiStack {
ui.stack()
.iter()
.find(|stack| {
stack.is_root_ui()
|| [Some(UiKind::Popup), Some(UiKind::Menu)].contains(&stack.kind())
|| stack.info.tags.contains(MenuConfig::MENU_CONFIG_TAG)
})
.expect("We should always find the root")
}
/// Is this Ui part of a menu?
///
/// Returns `false` if this is a menu bar.
/// Should be used to determine if we should show a menu button or submenu button.
pub fn is_in_menu(ui: &Ui) -> bool {
for stack in ui.stack().iter() {
if let Some(config) = stack
.info
.tags
.get_downcast::<MenuConfig>(MenuConfig::MENU_CONFIG_TAG)
{
return !config.bar;
}
if [Some(UiKind::Popup), Some(UiKind::Menu)].contains(&stack.kind()) {
return true;
}View on GitHub (pinned to 8fb03c9ae9)