Windows: startup bundled-plugins reconcile races Chrome extension-host.exe (EBUSY) — Computer Use + Chrome plugins disappear; CU helper "paths unavailable"

Open 💬 5 comments Opened Jun 9, 2026 by pdwhoward
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

26.602.9276.0 (also reproduced on 26.602.4764.0)

What subscription do you have?

Pro

What platform is your computer?

_No response_

What issue are you seeing?

On Windows, the desktop app's startup "bundled plugins reconcile" rebuilds %USERPROFILE%\.codex\.tmp\bundled-marketplaces\openai-bundled by deleting and re-copying it from the app bundle. If the Chrome plugin's native messaging host (extension-host.exe, spawned by Chrome, survives Codex restarts) is still running, it holds a handle inside that folder and the delete fails with EBUSY. The reconcile then aborts mid-way, leaving the runtime marketplace partially deleted (only plugins\chrome remains; .agents\plugins\marketplace.json is gone).

Consequences after every restart while Chrome's host is alive:

  1. Computer Use and Chrome plugins disappear from the marketplace/plugin model.
  2. The Computer Use native pipe fails on a loop (~every 10–30 s):
warning [computer-use-native-pipe] computer-use native pipe startup failed
        errorMessage="Windows Computer Use helper paths are unavailable"
info    [computer-use-native-pipe] computer-use notify config ensure finished
        platform=win32 reason=missing-helper-path status=skipped
  1. Because the aborted reconcile is also what stages plugin caches, the per-user cache (.codex\plugins\cache\openai-bundled\computer-use\<version>) is never populated for a new bundled plugin version after an app update. The CU helper resolver builds its path from the bundled manifest version (plugin.json → localVersion), so it points at a non-existent directory and throws Windows Computer Use helper paths are unavailable even though codex-computer-use.exe ships in the app bundle.

Key log lines from one startup (build 26.602.9276.0):

15:02:17.657Z info [bundled-plugins] bundled_plugins_reconcile_started reason=startup
15:02:32.863Z warning [BundledPluginsMarketplace] bundled_plugins_marketplace_resolve_failed
              errorCode=EBUSY errorMessage="EBUSY: resource busy or locked, rmdir
              'C:\Users\<user>\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\chrome\extension-host\windows\x64'"
15:02:33.976Z warning [computer-use-native-pipe] computer-use native pipe startup failed
              errorMessage="Windows Computer Use helper paths are unavailable"
15:02:34.017Z info [bundled-plugins] bundled_plugins_reconcile_completed reason=startup

The lock holder (confirmed with a rename test + process inspection): a stale extension-host.exe running since a previous session, command line extension-host.exe chrome-extension://hehggadaopoacecdllhhajmbjkdcmajg/ --parent-window=0, image path .codex\plugins\cache\openai-bundled\chrome\latest\extension-host\windows\x64\extension-host.exe. It is launched by Chrome (native messaging), so quitting/restarting Codex does not stop it — one stale host breaks every subsequent launch.

What steps can reproduce the bug?

  1. Windows 11, Codex desktop app, Chrome plugin enabled, Codex Chrome extension installed and used at least once (so extension-host.exe is running).
  2. Quit Codex completely and relaunch it (the extension-host survives because Chrome owns it).
  3. Watch the desktop log: bundled_plugins_marketplace_resolve_failed errorCode=EBUSY, then Computer Use + Chrome disappear from Plugins, and the computer-use native pipe loops "Windows Computer Use helper paths are unavailable".

What is the expected behavior?

Startup reconcile should tolerate a running extension-host: plugins should not vanish after a restart, and the Computer Use helper should start.

Additional information

Verified workaround (root-cause confirmation)

Kill the Chrome-extension host right before/while launching Codex so the reconcile window completes cleanly:

Get-CimInstance Win32_Process -Filter "Name='extension-host.exe'" |
  Where-Object { $_.CommandLine -like '*hehggadaopoacecdllhhajmbjkdcmajg*' } |
  ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
# then launch Codex; reconcile completes with no EBUSY,
# computer-use native pipe reports "startup ready",
# and the reconcile itself re-stages the missing plugin cache version.

With this, the same build goes from permanently broken to fully working (verified across 5+ restarts), which confirms the race is the root cause. The host respawns afterwards and Chrome control keeps working.

Suggested fixes

  • Stage the new marketplace copy to a temp directory and atomically swap/rename, instead of delete-then-recopy in place.
  • Or: treat EBUSY on individual entries as non-fatal (skip + retry) rather than aborting the whole reconcile, so other plugins (computer-use, marketplace.json) still get materialized.
  • Or: have the app terminate/coordinate with its own extension-host.exe before the reconcile delete.
  • Decouple cache staging from the .tmp rebuild so a failed .tmp delete can't leave the Computer Use helper cache unstaged after an app update.

Environment

  • Codex desktop (MSIX): 26.602.9276.0 (also reproduced on 26.602.4764.0)
  • Bundled plugins version: 26.602.71036
  • Windows 11 Enterprise 10.0.26200, x64
  • Chrome with Codex extension (hehggadaopoacecdllhhajmbjkdcmajg)

Possibly related: #25962, #26204 (same user-visible symptom "Computer Use unavailable" on Windows; the mechanism above may explain them).

View original on GitHub ↗

5 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #27152
  • #25795
  • #25780

Powered by Codex Action

RedLynx101 · 2 months ago

Additional confirmation from another Windows Codex Desktop install. This still reproduces on:

  • Codex Desktop: OpenAI.Codex_26.609.9530.0_x64__2p2nqsd0c76g0
  • OS: Windows
  • Bundled Chrome plugin enabled, Codex Chrome extension/native host active

Observed on startup:

2026-06-16T04:17:07.864Z info [browser-use-native-pipe-server] browser-use native pipe listening pipePath=\\.\pipe\codex-browser-use-...
2026-06-16T04:17:12.635Z info [computer-use-native-pipe] computer-use native pipe startup ready pipePath=\\.\pipe\codex-computer-use-... platform=win32
2026-06-16T04:17:15.886Z warning [BundledPluginsMarketplace] bundled_plugins_marketplace_resolve_failed errorCode=EBUSY errorMessage="EBUSY: resource busy or locked, rmdir '%USERPROFILE%\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins\chrome\extension-host\windows\x64'"
2026-06-16T04:17:19.674Z info [bundled-plugins] bundled_plugins_reconcile_completed hasExternalPluginStateSync=true reason=startup

After that reconcile failure, the generated marketplace was left partially populated:

%USERPROFILE%\.codex\.tmp\bundled-marketplaces\openai-bundled\plugins
└── chrome

The generated copies of browser, computer-use, latex, and sites were missing, including required files such as:

  • browser/.codex-plugin/plugin.json
  • browser/scripts/browser-client.mjs
  • computer-use/.codex-plugin/plugin.json
  • computer-use/scripts/computer-use-client.mjs

The installed package source was intact and contained all bundled plugins:

C:\Program Files\WindowsApps\OpenAI.Codex_26.609.9530.0_x64__2p2nqsd0c76g0\app\resources\plugins\openai-bundled\plugins
browser
chrome
computer-use
latex
sites

The lock holder was a running Chrome native host process from the user plugin cache:

%USERPROFILE%\.codex\plugins\cache\openai-bundled\chrome\latest\extension-host\windows\x64\extension-host.exe

A non-destructive local repair confirmed the diagnosis: copying the missing plugin folders from the installed package back into the generated marketplace, while leaving the locked chrome/extension-host directory alone, restored the surfaces. After that:

  • generated Computer Use client: sky.list_apps() returned 40 apps
  • generated Browser client: connected as iab
  • Chrome/Comet bridge: connected as extension

Expected behavior: bundled plugin reconcile should tolerate a running Chrome native host, or isolate that failure so one locked Chrome directory cannot leave the generated marketplace missing Browser/Computer Use/LaTeX/Sites. Reconcile should either skip the locked extension-host subtree, stage atomically, or stop/restart the native host before replacing it.

CyrusAuyeung · 2 months ago

I traced the public repo side of this failure and prepared a tested mitigation branch, but I cannot open an upstream PR from this account because GitHub rejects CreatePullRequest against openai/codex for this user. Leaving the patch here so a maintainer or someone with PR permission can cherry-pick it or open the upstream PR.

Patch:

Public code paths I found:

  • codex-rs/core-plugins/src/store.rs: plugin cache install/replace/remove path.
  • codex-rs/core-plugins/src/store_tests.rs: plugin cache unit tests.
  • codex-rs/core-plugins/src/marketplace_upgrade/activation.rs: installed marketplace activation rollback logic.
  • codex-rs/core-plugins/src/marketplace_upgrade/activation_tests.rs: added rollback coverage.

Important limitation: the public checkout does not contain the Desktop bundled reconciler symbols from the logs (BundledPluginsMarketplace, bundled_plugins_marketplace_resolve_failed, plugin_marketplace_folder_write_failed, extension-host launch/native-host path generation, etc.). Those appear to live in Desktop/bundled private code. So this patch hardens the public plugin-cache side and adds regression coverage, but the Desktop bundled marketplace staging/reconcile code still needs a private-side fix.

What the patch does:

  • Adds bounded Windows retry/backoff around plugin cache remove_dir_all, remove_file, and rename operations when Windows reports lock-like failures (ACCESS_DENIED, sharing violation, lock violation, directory-not-empty).
  • Keeps fail-closed behavior: retry exhaustion returns an error, it does not silently ignore the failure.
  • Preserves the existing cache root when replacing an existing plugin cache entry cannot proceed because a file is still locked.
  • Emits a warning after retry exhaustion so locked-cache failures have explicit telemetry.
  • Adds a regression test that installing from a .tmp/bundled-marketplaces plugin source materializes into the stable plugins/cache/<marketplace>/<plugin>/<version> root rather than an active .tmp path.
  • Adds Windows tests for transient and persistent file locks around an existing cache entry.
  • Adds marketplace activation rollback coverage for post-activation failures.

What still needs to happen in Desktop/private code:

  • The bundled marketplace reconcile should stage into a unique directory, validate marketplace.json and required plugin.json files, then atomically switch only after validation succeeds.
  • If deleting/replacing the old runtime marketplace fails on Windows because extension-host.exe or a loaded native module still holds a handle, the old usable runtime marketplace should remain active.
  • The plugin cache should never activate a latest/active root that points into .tmp/bundled-marketplaces.
  • A locked Chrome extension-host subtree should not leave Browser / Computer Use / LaTeX / Sites missing from the generated marketplace.

Validation run on Windows:

  • just fix -p codex-core-plugins
  • Passed with an existing unrelated clippy::large_enum_variant warning in core-plugins/src/manifest.rs.
  • just test -p codex-core-plugins
  • 247 tests passed, including the new Windows lock tests and .tmp cache-root regression.
  • git diff --check
  • Passed.
Necmttn · 2 months ago

Bundled plugin reconcile should be atomic and receipt-driven. Stage to a new directory, verify manifest and helper paths, swap by rename, and keep the previous good marketplace if cleanup hits EBUSY. A reconcile receipt with plugin, source version, lock holder if known, status, and rollback path would keep one Chrome host handle from removing unrelated tools.

---

_Generated with ax._

zemeng5208 · 16 days ago

I maintain WinBridge Recovery, an independent Windows recovery tool for Codex Desktop: https://github.com/zemeng5208/winbridge-recovery

This is a strong match for the local-state recovery path the project handles. v3.1.1 already closes Chrome/Edge before repair, stops known Codex/browser helper processes, refuses to enter destructive replacement if targets are still locked, stages replacement content separately, validates it, and uses atomic swaps + rollback/backups for the marketplace/cache state. It also validates plugin versions, latest, runtime paths, and Native Host state after recovery.

The important part of this report is that killing a process name once is not enough when Chrome can immediately respawn the Native Messaging host. I am tracking more precise lock-owner diagnostics (PID / executable path / command line and path-based ownership) so the recovery flow can distinguish the Codex Chrome host from unrelated node.exe/browser processes instead of using broad process-name kills.

So if the failure is EBUSY / os error 5 leaving openai-bundled partial or the plugin cache/latest inconsistent, WinBridge is intended to help recover that state from the official installed package. It does not attempt to fix model-side Chrome routing or other upstream runtime behavior, and it will stop rather than force a swap while a target remains locked.