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

  1. Ensure the bridge is injected and healthy before calling install_native_menu_localizer (e.g. wait for bridge_health_ok).
  2. Increase MENU_LOCALIZATION_RETRY_DELAY or retry count if the app starts slowly.
  3. Log/inspect the underlying last_error to see the real cause; fix that first.
  4. 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

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)