{"record":{"id":"35af67edf4877fc9","repo":"BigPizzaV3/CodexPlusPlus","slug":"native-menu-localization-failed","errorCode":null,"errorMessage":"native menu localization failed","messagePattern":"native menu localization failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/codex-plus-core/src/native_menu.rs","lineNumber":112,"sourceCode":"    let mut last_error = None;\n    for attempt in 1..=MENU_LOCALIZATION_RETRIES {\n        match try_install_native_menu_localizer(inspector_port).await {\n            Ok(()) => return Ok(()),\n            Err(error) => {\n                last_error = Some(error);\n                let _ = crate::diagnostic_log::append_diagnostic_log(\n                    \"native_menu.localization_retry_failed\",\n                    json!({\n                        \"inspector_port\": inspector_port,\n                        \"attempt\": attempt,\n                        \"message\": last_error.as_ref().map(ToString::to_string).unwrap_or_default()\n                    }),\n                );\n                tokio::time::sleep(MENU_LOCALIZATION_RETRY_DELAY).await;\n            }\n        }\n    }\n    Err(last_error.unwrap_or_else(|| anyhow::anyhow!(\"native menu localization failed\")))\n}\n\npub fn native_menu_localizer_script() -> anyhow::Result<String> {\n    let translations =\n        serde_json::to_string(&MENU_LABEL_TRANSLATIONS.iter().copied().collect::<Vec<_>>())?;\n    Ok(format!(\n        r#\"\n(() => {{\n  const translations = new Map({translations});\n  const electron = process.mainModule?.require?.(\"electron\");\n  if (!electron?.Menu) return JSON.stringify({{ status: \"skipped\", reason: \"electron-menu-unavailable\" }});\n  const Menu = electron.Menu;\n  let changed = 0;\n  const translateItem = (item) => {{\n    if (!item) return;\n    const nextLabel = translations.get(item.label);\n    if (nextLabel && item.label !== nextLabel) {{\n      item.label = nextLabel;","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/native_menu.rs#L94-L130","documentation":"install_native_menu_localizer retries applying the native menu localization script to the Codex window several times, recording the last failure. If all retries are exhausted without success it throws this fallback error. It signals the native UI menu could not be localized (labels remain untranslated).","triggerScenarios":"The retry loop's evaluate-script calls kept failing (window not ready, bridge not injected, script evaluation error) until attempts ran out; last_error is None or the wrapped cause.","commonSituations":"Bridge script not yet injected when the localizer runs; Codex window opened late so the menu DOM is absent during retries; an upstream update changed menu structure so the script no longer matches.","solutions":["Ensure the bridge is injected and healthy before calling install_native_menu_localizer (e.g. wait for bridge_health_ok).","Increase MENU_LOCALIZATION_RETRY_DELAY or retry count if the app starts slowly.","Log/inspect the underlying last_error to see the real cause; fix that first.","Re-run localization manually after the window is fully loaded."],"exampleFix":"// before: fire localizer immediately at startup\ninstall_native_menu_localizer().await?;\n// after: wait for bridge health first\nwhile !bridge_health_ok(debug_port).await? {\n    tokio::time::sleep(Duration::from_millis(500)).await;\n}\ninstall_native_menu_localizer().await?;","handlingStrategy":"retry","validationCode":"// wait until bridge is healthy before localizing menus\nwhile !bridge_health_ok(debug_port).await.unwrap_or(false) {\n    tokio::time::sleep(Duration::from_millis(500)).await;\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = install_native_menu_localizer().await {\n    log::warn!(\"menu localization skipped: {e:#}\"); // non-fatal: menus stay untranslated\n}","preventionTips":["Ensure bridge injection completes before localization starts","Allow generous retry delay for slow app startup","Treat localization failure as non-fatal and log underlying cause","Verify native_menu_localizer_script() output still matches current menu structure after upstream updates"],"tags":["localization","native-menu","retry-exhausted"],"backgroundTag":"retry-limit-exceeded","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}