Chatwidget tests leak temporary CODEX_HOME directories

Open 💬 0 comments Opened Jul 11, 2026 by askac

What issue are you seeing?

Codex TUI chatwidget tests permanently leave temporary CODEX_HOME directories under the system temporary directory.

The directories are named chatwidget-tests-*. On my FreeBSD development system, repeated test runs accumulated 7,767 directories. At least 321 were non-empty, using approximately 634 MiB in total.

A single filtered chatwidget test also reproduces the leak on WSL2/Linux, leaving one directory after the test exits normally.

What steps can reproduce the bug?

Using commit 5c19155cbd93bfa099016e7487259f61669823ff:

  1. Create an isolated temporary root:

probe_root=$(mktemp -d /tmp/chatwidget-leak.XXXXXX)

  1. From codex-rs, run one chatwidget test:

TMPDIR="$probe_root" TMP="$probe_root" TEMP="$probe_root" \
just test \
-p codex-tui \
--lib \
-E 'test(=chatwidget::tests::popups_and_settings::plugins_popup_loading_state_snapshot)'

  1. Inspect the temporary root:

find "$probe_root" -maxdepth 4 -printf '%y %p -> %l\n' | sort

The test passes, but one chatwidget-tests-* directory remains.

Observed WSL2 result:

RESULT: REPRODUCED
Leftover chatwidget-tests directories: 1

What is the expected behavior?

Temporary CODEX_HOME directories created by chatwidget test fixtures should remain available for the lifetime of their test and then be removed automatically when the test finishes.

Successful test runs should not permanently accumulate chatwidget-tests-* directories under /tmp.

Additional information

Root cause:

codex-rs/tui/src/chatwidget/tests/helpers.rs::test_config() creates a TempDir and immediately calls .keep(). The returned Config stores only path values, so the TempDir cleanup guard is discarded and automatic cleanup is permanently disabled.

This is separate from #32374. That issue involves test-binary guards stored in Rust statics; this issue is caused by an explicit .keep() in the chatwidget fixture.

I prepared a candidate fix:

https://github.com/askac/codex/commit/02a5f08983a083e3e9250d0866072a555a4711ea

Full comparison:

https://github.com/openai/codex/compare/main...askac:fix-chatwidget-test-tempdir-cleanup

The candidate fix:

  • retains each TempDir guard in a thread-local registry;
  • keeps the temporary CODEX_HOME alive for the complete test-thread lifetime;
  • allows normal TempDir cleanup when the test thread exits;
  • does not change production ChatWidget or Config types;
  • does not require changes to the hundreds of existing helper call sites;
  • does not add dependencies or lockfile changes;
  • adds a self-reexec regression test that checks for leftovers after the child test thread exits.

WSL2/Linux verification:

Before the fix:

RESULT: REPRODUCED
Leftover chatwidget-tests directories: 1

After the fix, using the same existing chatwidget test:

PASS codex-tui chatwidget::tests::popups_and_settings::plugins_popup_loading_state_snapshot
RESULT: NOT REPRODUCED

The patched probe root was empty after the successful test.

The repository currently limits pull request creation to collaborators, so I am providing the reproduction, root-cause analysis, and public candidate fix here first.

View original on GitHub ↗