Plugin cache refresh can keep stale bundled/local plugin contents when source changes without a version bump
What version of the Codex App are you using?
Observed with Codex Desktop for Windows app package OpenAI.Codex_26.429.3425.0_x64__2p2nqsd0c76g0.
What platform is your computer?
Windows.
What issue are you seeing?
Codex can continue loading stale plugin contents from ~/.codex/plugins/cache after the underlying bundled/local marketplace plugin source has changed, if the plugin manifest version string did not change.
I observed this with the bundled Browser Use plugin:
~/.codex/plugins/cache/openai-bundled/browser-use/0.1.0-alpha1/
The installed app bundle had newer Browser Use plugin files, including scripts/browser-client.mjs, but Codex continued to load the older cached copy because the plugin manifest still reported:
"version": "0.1.0-alpha1"
Manually comparing the app-bundled Browser Use source against the active cache showed stale cached runtime content. Syncing the cache from the current source fixed the Browser Use behavior locally, which points at cache invalidation rather than the local device as the underlying failure mode.
This is dangerous for bundled/alpha plugin assets because a plugin can receive behavior fixes without a manifest version bump, while Codex treats the existing cache directory as fresh solely because the version directory already exists.
What steps can reproduce the bug?
A minimal reproduction should be possible with any local/non-curated marketplace plugin:
- Install or enable a local marketplace plugin with a manifest version, for example
0.1.0-alpha1. - Let Codex install it into the persistent cache under:
~/.codex/plugins/cache/<marketplace>/<plugin>/<version>/
- Change the source plugin contents while keeping
.codex-plugin/plugin.jsonat the sameversionvalue. - Restart or continue Codex so plugin cache refresh runs.
- Observe that Codex keeps loading the old cache entry instead of reinstalling from the changed source.
For the observed Browser Use case, the source was the app-bundled openai-bundled/browser-use plugin and the stale active cache was:
~/.codex/plugins/cache/openai-bundled/browser-use/0.1.0-alpha1/
What is the expected behavior?
Plugin cache freshness should not be determined by plugin.json.version alone.
For local and bundled plugin sources, Codex should detect when source contents changed and reinstall/replace the cached plugin entry even if the manifest version string is unchanged.
A robust cache metadata record would likely include some combination of:
- source content digest,
- plugin manifest digest,
- source path or source identity,
- installed digest,
- app build/version for bundled plugin sources,
- marketplace revision where applicable.
If the source digest or bundle provenance changes, Codex should atomically replace the cached entry. If Codex intentionally relies on plugin authors bumping versions for every bundled asset change, that should be enforced in release tooling or surfaced clearly when source and cache diverge.
Additional information
I searched existing issues for related cache/plugin reports before filing. These are adjacent but appear distinct:
- #19834 is about clearly identifying stale marketplace repository clones.
- #17001 is about confusion between source and cache directories.
- #18863 is about symlinks being dropped when copying plugin cache contents.
This issue is different: the source bundle/local marketplace can be current, but Codex still considers the persistent installed cache valid because the manifest version string is unchanged.
Relevant source-level behavior in the public repo:
codex-rs/core-plugins/src/store.rsPluginStore::plugin_root()stores plugins underplugins/cache/<marketplace>/<plugin>/<version>.PluginStore::active_plugin_version()discovers the active version from existing cache directory names.install_with_version()can atomically replace the cache, but only when refresh decides to call it.
codex-rs/core-plugins/src/loader.rsrefresh_non_curated_plugin_cache_with_mode()readsplugin_version_for_source(source_path)from the manifest.- In
IfVersionChangedmode it skips reinstall whenstore.active_plugin_version(&plugin_id) == Some(plugin_version). load_plugin()then loads fromstore.active_plugin_root().
The problem is the missing content/provenance validation between “source plugin at this same version” and “installed cache entry for this version.”
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗