{"record":{"id":"b626a18e144d7c6b","repo":"cjpais/Handy","slug":"failed-to-create-secure-input-warning-item","errorCode":null,"errorMessage":"failed to create secure input warning item","messagePattern":"failed to create secure input warning item","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/tray.rs","lineNumber":202,"sourceCode":"}\n\n/// Gets the appropriate icon path for the given theme and state.\n///\n/// `warning` overlays a badge on the idle icon while keyboard shortcuts are\n/// blocked (macOS Secure Input); recording/transcribing states keep their\n/// normal icons so in-flight activity stays recognizable.\npub fn get_icon_path(theme: AppTheme, state: TrayIconState, warning: bool) -> &'static str {\n    if warning && state == TrayIconState::Idle {\n        return match theme {\n            AppTheme::Dark => \"resources/tray_idle_warning.png\",\n            AppTheme::Light => \"resources/tray_idle_warning_dark.png\",\n            // Linux never sets the warning flag (Secure Input is macOS-only),\n            // but fall back to the normal icon just in case.\n            AppTheme::Colored => \"resources/handy.png\",\n        };\n    }\n    match (theme, state) {\n        // Dark theme uses light icons\n        (AppTheme::Dark, TrayIconState::Idle) => \"resources/tray_idle.png\",\n        (AppTheme::Dark, TrayIconState::Recording) => \"resources/tray_recording.png\",\n        (AppTheme::Dark, TrayIconState::Transcribing) => \"resources/tray_transcribing.png\",\n        // Light theme uses dark icons\n        (AppTheme::Light, TrayIconState::Idle) => \"resources/tray_idle_dark.png\",\n        (AppTheme::Light, TrayIconState::Recording) => \"resources/tray_recording_dark.png\",\n        (AppTheme::Light, TrayIconState::Transcribing) => \"resources/tray_transcribing_dark.png\",\n        // Colored theme uses pink icons (for Linux)\n        (AppTheme::Colored, TrayIconState::Idle) => \"resources/handy.png\",\n        (AppTheme::Colored, TrayIconState::Recording) => \"resources/recording.png\",\n        (AppTheme::Colored, TrayIconState::Transcribing) => \"resources/transcribing.png\",\n    }\n}\n\n/// Sets the recording state shown by the tray (icon + Cancel/model menu).\npub fn set_tray_state(app: &AppHandle, state: TrayIconState) {\n    sync_tray_with(app, |inner| inner.icon_state = state);\n}","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/cjpais/Handy/blob/fbd4e15fa14a721c66c57006ae110428b9e255b3/src-tauri/src/tray.rs#L184-L220","documentation":"Panic when muda's MenuItem::with_id fails to create the optional 'secure_input_warning' tray item on macOS. The item is only built while Secure Input is engaged (secure_input warning active). Creation fails when the menu resource cannot be allocated — typically a duplicated id within the menu, an invalid id/label, or tray/menu rebuild racing app teardown when the app handle is no longer usable.","triggerScenarios":"create/update tray while Secure Input is active (e.g. a password prompt grabbed it) and MenuItem::with_id(app, \"secure_input_warning\", label, true, None) errors — id collision with another item, or a rebuild racing shutdown.","commonSituations":"Tray icon refresh (theme change triggers refresh_tray_icon) racing quit; forks adding items that reuse the id; macOS menu services under load or during process teardown.","solutions":["Ensure the id 'secure_input_warning' is used exactly once per menu build","Guard tray rebuild paths against app teardown (check the app is still running before rebuilding)","Treat this optional warning item as skippable: log and continue without it instead of expecting"],"exampleFix":"// before\nlet secure_input_warning = crate::secure_input::tray_warning_active(app).then(|| {\n    MenuItem::with_id(app, \"secure_input_warning\", &label, true, None::<&str>)\n        .expect(\"failed to create secure input warning item\")\n});\n\n// after — optional item degrades instead of aborting tray creation\nlet secure_input_warning = crate::secure_input::tray_warning_active(app).and_then(|_| {\n    match MenuItem::with_id(app, \"secure_input_warning\", &label, true, None::<&str>) {\n        Ok(item) => Some(item),\n        Err(e) => {\n            log::warn!(\"skipping secure input tray item: {e}\");\n            None\n        }\n    }\n});","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match MenuItem::with_id(app, \"secure_input_warning\", &label, true, None::<&str>) {\n    Ok(item) => Some(item),\n    Err(e) => {\n        log::warn!(\"secure input tray item skipped: {e}\");\n        None // build the tray without the optional warning line\n    }\n}","preventionTips":["Treat optional tray items as skippable: log-and-continue instead of expect","Guard tray rebuilds against app teardown (theme changes fire rebuilds)","Centralize tray item ids in one constants module to prevent collisions"],"tags":["rust","tauri","tray","muda","macos","secure-input"],"backgroundTag":"tray-menu-item-creation-failed","analyzedSha":"fbd4e15fa14a721c66c57006ae110428b9e255b3","analyzedAt":"2026-08-17T10:29:55.597Z","contentChangedAt":"2026-08-17T10:29:55.597Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}