[Windows] CUA node_repl workers remain after Code Mode task completion and correlate with system-wide UI stalls
Summary
On Windows, the Codex desktop app can become severely sluggish during and after a long Code Mode task that creates and repeatedly validates an interactive HTML presentation. Mouse movement and window interaction then stutter across the system, even though CPU is not saturated, disk I/O is low, and substantial physical memory remains available.
Completing the task does not reliably recover the machine. Fully exiting the Codex desktop app immediately restores normal responsiveness because it terminates the shared app-server and Code Mode runtime process tree.
Environment
- OS: Windows 11 x64
- Desktop app package:
OpenAI.Codex_26.810.6296.0_x64 - CUA Node runtime:
cua-node 0.0.8 - Node version:
24.19.0 - Local app-server command includes:
features.code_mode_host=true app-server --analytics-default-enabled
Reproduction
- Start the Windows Codex desktop app.
- Run a task that creates or iterates on a rich interactive HTML presentation.
- Ask Codex to render/inspect the page and validate desktop/mobile layout and interactions using browser or Playwright-based checks.
- Repeat several iterations, including interaction and responsive-layout validation.
- After the task reports completion, continue using the desktop app and other Windows applications.
- Observe severe system-wide UI and mouse stutter. Fully exit the desktop app and observe that responsiveness returns.
Observed process behavior
codex.exeruns the shared localapp-serverand ownscodex-code-mode-host.exe.node_repl.exeprocesses from the bundledcua_noderuntime appear as direct children of the sameapp-serverprocess.- The
node_repl.execount reached 37 during the affected session. - After the HTML task became idle/completed, 21
node_repl.exeprocesses pluscodex-code-mode-host.exewere still present. - The main desktop process was approximately 1 GB working set; large renderer processes were approximately 0.6 GB and 0.2 GB.
- The OS process command line does not expose a thread/task ID, so I cannot assign every retained child to one conversation. Some later child processes were also created while collecting diagnostics. The correlation is nevertheless strongest around the repeated HTML/browser-validation task and the shared runtime lifecycle.
Performance evidence during the lag window
- Available memory was approximately 28--31 GB, so this did not look like simple physical-memory exhaustion.
- Hard page reads and writes were near zero or very low; disk queue and latency were low.
- Windows soft/transition-fault activity became extremely high, approximately 430k--470k events/sec in the worst observed samples.
- Memory Compression was approximately 3.8--3.95 GB.
- System CPU was only about 20--48% and was not saturated, but processor-queue spikes were observed.
- No Application Error or Application Hang event was recorded for the session.
- Fully exiting the desktop app terminated the shared runtime tree and immediately removed the stutter.
Expected behavior
When a Code Mode task reaches a terminal state, task-specific browser/Computer Use resources should be terminated and reaped, or a bounded shared worker pool should be reused. Multiple Codex conversations should not leave an accumulating set of runtime workers that can make the Windows desktop unresponsive.
The desktop UI should remain responsive after a task completes without requiring a full application restart.
Requested investigation
Please instrument the CUA/Code Mode spawn and cleanup lifecycle with a task/run ID, spawned PID, parent PID, terminal reason, terminate result, and wait/reap result. In particular, verify whether node_repl workers are intentionally shared, whether they are expected to survive a completed task, and whether the number of workers is bounded and reused rather than recreated per task.
If workers are task-owned, please add a regression test covering completion, cancellation, error, tool timeout, and app-server disconnect paths. If they are intentionally shared, please verify that completed tasks release their browser/runtime state and that the shared pool cannot grow without bound.
Related issues
- #35582 -- Desktop retains completed CUA
node_replworkers on macOS. - #38093 -- Code Mode can report a terminal result while child work is still alive.
- #38713 -- Windows desktop main-process thrash after opening an already-running app; related symptom, different trigger.
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional Windows reproduction: generated config returned, then 24 workers accumulated
I reproduced this independently on Windows 11 (
10.0.26200) with Codex Desktop26.810.6296.0.A previous workaround had commented out the global
node_replMCP block. After restarting Codex, the Desktop/plugin runtime generated an active[mcp_servers.node_repl]block inconfig.tomlagain. Playwright remained disabled and its process count stayed at zero, so this recurrence was isolated from the separate Playwright MCP duplication.Within about 68 minutes of app-server uptime, I captured:
node_repl.exeprocesses, all direct children of the samecodex.exeapp-server.I then terminated exactly those 24 workers:
node_repl.exe: 24 -> 0After commenting out the regenerated block again,
codex mcp listparsed successfully and listed nonode_replserver. This workaround is therefore effective only until Desktop/plugin configuration generation re-adds the server.There also appears to be a separable main-process runtime-validation/read-loop regression tracked in #38518. In an earlier capture during the same investigation, the top-level
ChatGPT.exesustained about 1.14 GiB/s logical reads and ~142% of one core while physical disk/network activity was low. Killing the retained workers dramatically reduced process/thread/handle pressure and restored perceived responsiveness, but did not stop that main-process read loop during active diagnostics. This suggests the worker lifecycle leak and the main-process validation loop can coexist.No raw logs, session content, usernames, machine-specific paths, task identifiers, or account data are included here. I can capture a sanitized ETW trace if maintainers specify the desired providers and reproduction boundary.
Additional lifecycle/config observation: generated block returns even when related plugins are disabled
After a full Desktop restart with bundled
chrome,browser, andcomputer-useplugins explicitly set toenabled = false, Desktop still regenerated an active[mcp_servers.node_repl]block and spawned 5 directnode_repl.exeworkers within minutes.Using the documented MCP setting below was more durable than commenting/removing the generated block:
After adding that field:
codex mcp listreportednode_replasdisabled;This suggests the Desktop generator currently recreates the server definition independently of the three related plugin enable flags. It should preserve an explicit user-level
enabled = falseoverride and must not spawn the server when that override is present.No session content, account details, usernames, local paths, or raw logs are attached.
Additional source-level evidence from affected Windows Desktop build
26.810.4967.0narrows the worker-retirement failure:activeorinProgressare excluded from TTL retirement. Stale task state can keep a runtime alive indefinitely.This is consistent with completed tasks retaining the workers reported here. A focused regression test should resume six owner tasks, leave only one active, and assert that the two oldest inactive owners unsubscribe without waiting one hour. The candidate set should include the de-duplicated union of oldest over-budget IDs and TTL-expired IDs.
activeandinProgressstate also need a bounded work lease or watchdog.This evidence was initially reported in #38784. I am closing that umbrella report so worker lifecycle remains tracked here.