Marketplace upgrade staging directories leak in `.tmp/marketplaces/.staging/`

Open 💬 2 comments Opened May 4, 2026 by robotlearning123

Summary

Marketplace upgrade and add operations create temporary staging directories under <CODEX_HOME>/.tmp/marketplaces/.staging/ with prefixes marketplace-upgrade-* and marketplace-add-*. If the process crashes or is killed during these operations, the TempDir destructor never runs and these directories accumulate permanently with no cleanup.

On an active installation this can grow to hundreds of GB over time (each git clone is ~230MB). I personally found 2293 orphaned directories totalling 187GB on a single machine:

$ du -sh ~/.codex/.tmp/marketplaces/.staging/
187G

$ ls ~/.codex/.tmp/marketplaces/.staging/ | wc -l
2293

Root Cause

There are three leak paths:

  1. Process crash/kill: TempDir in marketplace_upgrade.rs:195-203 is never dropped, staging dir is orphaned permanently.
  2. Git clone timeout (30s in git.rs): Partially cloned directories remain in .staging/ with no cleanup.
  3. Activation error path in activation.rs:94-127: backup_dir.keep() is called on double-failure (rename fails AND rollback fails), permanently preserving marketplace-backup-* directories.

There is no equivalent of remove_stale_curated_repo_temp_dirs() (which exists in startup_sync.rs:258-341 for plugins-clone-* dirs) for the marketplace staging path.

Proposed Fix

Add remove_stale_marketplace_temp_dirs() modeled after the existing cleanup in startup_sync.rs, called at the start of:

  • upgrade_configured_git_marketplaces()
  • add_marketplace_sync_with_cloner()

Cleans up directories older than 10 minutes, covering:

  • marketplace-upgrade-* in .staging/
  • marketplace-add-* in .staging/
  • marketplace-backup-* at the install root level

Related

  • #16004 — similar leak for plugins-clone-* directories in startup_sync.rs
  • #19834 — stale marketplace clone discoverability (separate concern)

View original on GitHub ↗

2 Comments

zichen0116 · 3 months ago

I dug through the code paths for this and the report looks correct.

Root cause confirmed

There is already a stale temp-dir cleanup pattern for curated plugin clones in:

  • codex-rs/core-plugins/src/startup_sync.rs
  • remove_stale_curated_repo_temp_dirs(...)

But the marketplace add/upgrade flows create analogous temp directories without any equivalent cleanup:

  • codex-rs/core-plugins/src/marketplace_upgrade.rs
  • creates .tmp/marketplaces/.staging/marketplace-upgrade-*
  • codex-rs/core-plugins/src/marketplace_add.rs
  • creates .tmp/marketplaces/.staging/marketplace-add-*
  • codex-rs/core-plugins/src/marketplace_upgrade/activation.rs
  • can preserve marketplace-backup-* under the install root on double-failure rollback paths

So if the process is interrupted or dies at the wrong point, these directories can accumulate indefinitely.

Proposed minimal fix

Add a marketplace-specific stale-dir cleanup helper, modeled closely on remove_stale_curated_repo_temp_dirs(...), and call it before creating new staging dirs in:

  • upgrade_configured_git_marketplaces(...)
  • add_marketplace_sync_with_cloner(...)

The helper would remove only old directories matching the known marketplace temp prefixes:

  • .staging/marketplace-upgrade-*
  • .staging/marketplace-add-*
  • install-root marketplace-backup-*

using the same conservative age-based approach as the curated-plugin cleanup.

Test plan

If this direction is welcome, I can put together a focused PR with:

  • targeted unit tests for stale marketplace dir cleanup behavior
  • coverage that only matching old temp dirs are removed
  • verification that fresh dirs and unrelated dirs are preserved

Given the contribution policy in docs/contributing.md, I wanted to check first: would a small PR for this specific fix be welcome?

zichen0116 · 3 months ago

I went ahead and prepared the fix on a fork branch so it is easy to review or cherry-pick if this direction makes sense.

Branch / commit

What the patch does

  • adds remove_stale_marketplace_temp_dirs(...) in core-plugins/src/installed_marketplaces.rs
  • cleans up old temp dirs matching:
  • .tmp/marketplaces/.staging/marketplace-upgrade-*
  • .tmp/marketplaces/.staging/marketplace-add-*
  • .tmp/marketplaces/marketplace-backup-*
  • calls that helper before new staging dirs are created in:
  • add_marketplace_sync_with_cloner(...)
  • upgrade_configured_git_marketplaces(...)

Test coverage / verification

Added coverage for:

  • helper behavior: only matching old marketplace temp dirs are removed
  • add-path integration: stale marketplace temp dirs are cleaned before a real marketplace add flow stages new content

Local verification completed:

  • cargo test -p codex-core-plugins installed_marketplaces::tests
  • cargo test -p codex-core-plugins marketplace_add::tests
  • just fmt

I also tried the repo-recommended lint pass (just fix -p codex-core-plugins), but on this Windows machine the repo-pinned 1.93.0 toolchain is currently failing before linting with:

  • the 'cargo-clippy.exe' binary ... is not applicable to the '1.93.0-x86_64-pc-windows-msvc' toolchain

So I did not open a PR yet. If this specific fix is welcome under the current contribution policy, I can turn it into a proper PR immediately.