BigPizzaV3/CodexPlusPlus · warning
native menu localization failed
Error message
native menu localization failed
What it means
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).
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.
Example fix
// before: fire localizer immediately at startup
install_native_menu_localizer().await?;
// after: wait for bridge health first
while !bridge_health_ok(debug_port).await? {
tokio::time::sleep(Duration::from_millis(500)).await;
}
install_native_menu_localizer().await?; Defensive patterns
Strategy: retry
Validate before calling
// wait until bridge is healthy before localizing menus
while !bridge_health_ok(debug_port).await.unwrap_or(false) {
tokio::time::sleep(Duration::from_millis(500)).await;
} Try / catch
if let Err(e) = install_native_menu_localizer().await {
log::warn!("menu localization skipped: {e:#}"); // non-fatal: menus stay untranslated
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/35af67edf4877fc9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/native_menu.rs:112
let mut last_error = None;
for attempt in 1..=MENU_LOCALIZATION_RETRIES {
match try_install_native_menu_localizer(inspector_port).await {
Ok(()) => return Ok(()),
Err(error) => {
last_error = Some(error);
let _ = crate::diagnostic_log::append_diagnostic_log(
"native_menu.localization_retry_failed",
json!({
"inspector_port": inspector_port,
"attempt": attempt,
"message": last_error.as_ref().map(ToString::to_string).unwrap_or_default()
}),
);
tokio::time::sleep(MENU_LOCALIZATION_RETRY_DELAY).await;
}
}
}
Err(last_error.unwrap_or_else(|| anyhow::anyhow!("native menu localization failed")))
}
pub fn native_menu_localizer_script() -> anyhow::Result<String> {
let translations =
serde_json::to_string(&MENU_LABEL_TRANSLATIONS.iter().copied().collect::<Vec<_>>())?;
Ok(format!(
r#"
(() => {{
const translations = new Map({translations});
const electron = process.mainModule?.require?.("electron");
if (!electron?.Menu) return JSON.stringify({{ status: "skipped", reason: "electron-menu-unavailable" }});
const Menu = electron.Menu;
let changed = 0;
const translateItem = (item) => {{
if (!item) return;
const nextLabel = translations.get(item.label);
if (nextLabel && item.label !== nextLabel) {{
item.label = nextLabel;View on GitHub (pinned to b1ed92e5e4)