{"record":{"id":"70a9038d7f77ac90","repo":"tauri-apps/tauri","slug":"not-an-iconmenuitem","errorCode":null,"errorMessage":"Not an IconMenuItem","messagePattern":"Not an IconMenuItem","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri/src/menu/mod.rs","lineNumber":673,"sourceCode":"    match self {\n      MenuItemKind::Check(i) => i,\n      _ => panic!(\"Not a CheckMenuItem\"),\n    }\n  }\n\n  /// Casts this item to a [`IconMenuItem`], and returns `None` if it wasn't.\n  pub fn as_icon_menuitem(&self) -> Option<&IconMenuItem<R>> {\n    match self {\n      MenuItemKind::Icon(i) => Some(i),\n      _ => None,\n    }\n  }\n\n  /// Casts this item to a [`IconMenuItem`], and panics if it wasn't.\n  pub fn as_icon_menuitem_unchecked(&self) -> &IconMenuItem<R> {\n    match self {\n      MenuItemKind::Icon(i) => i,\n      _ => panic!(\"Not an IconMenuItem\"),\n    }\n  }\n}\n\nimpl<R: Runtime> Clone for MenuItemKind<R> {\n  fn clone(&self) -> Self {\n    match self {\n      Self::MenuItem(i) => Self::MenuItem(i.clone()),\n      Self::Submenu(i) => Self::Submenu(i.clone()),\n      Self::Predefined(i) => Self::Predefined(i.clone()),\n      Self::Check(i) => Self::Check(i.clone()),\n      Self::Icon(i) => Self::Icon(i.clone()),\n    }\n  }\n}\n\nimpl<R: Runtime> sealed::IsMenuItemBase for MenuItemKind<R> {\n  fn inner_muda(&self) -> &dyn muda::IsMenuItem {","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/tauri-apps/tauri/blob/460ec35447493200d64290dd7f015d5a91d0fd58/crates/tauri/src/menu/mod.rs#L655-L691","documentation":"MenuItemKind::as_icon_menuitem_unchecked casts a menu item handle to an IconMenuItem reference. It panics when the underlying item is actually a MenuItem, Submenu, PredefinedMenuItem or CheckMenuItem rather than an icon item, because the '_ => panic!()' catch-all arm is reached.","triggerScenarios":"Calling as_icon_menuitem_unchecked on a MenuItemKind obtained from an event, menu iteration, or from building a menu with MenuBuilder, where the item was created as a plain MenuItem or Submenu instead of IconMenuItem::with_id.","commonSituations":"Storing heterogeneous MenuItemKind values in a Vec and assuming they are all icon items; dynamically populating menus from config and blindly downcasting; copy-pasting unchecked-cast code after switching the item constructor.","solutions":["Check the kind first with a match on MenuItemKind::Icon before casting","Use as_icon_menuitem (the checked variant returning Result) instead of the unchecked variant","Trace where the MenuItemKind came from and construct it as IconMenuItem::with_id"],"exampleFix":"// before\nlet icon_item = item.as_icon_menuitem_unchecked();\n// after\nlet icon_item = match item.kind() {\n  MenuItemKind::Icon(i) => i,\n  _ => anyhow::bail!(\"expected an IconMenuItem\"),\n};","handlingStrategy":"type-guard","validationCode":"fn as_icon(item: &MenuItemKind<R>) -> Option<&IconMenuItem<R>> {\n  match item { MenuItemKind::Icon(i) => Some(i), _ => None }\n}","typeGuard":"fn is_icon_menu_item<R: Runtime>(k: &MenuItemKind<R>) -> bool {\n  matches!(k, MenuItemKind::Icon(_))\n}","tryCatchPattern":"std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| item.as_icon_menuitem_unchecked()))\n  .map_err(|_| anyhow::anyhow!(\"item is not an IconMenuItem\"))","preventionTips":["Prefer as_icon_menuitem (Result-returning) over the _unchecked variant","Match on MenuItemKind explicitly instead of assuming the kind","Keep menu items stored with their concrete types when possible"],"tags":["menu","panic","downcast","rust"],"backgroundTag":"invalid-enum-value","analyzedSha":"460ec35447493200d64290dd7f015d5a91d0fd58","analyzedAt":"2026-09-18T23:55:51.277Z","contentChangedAt":"2026-09-18T23:55:51.277Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}