[Windows] CUA node_repl workers remain after Code Mode task completion and correlate with system-wide UI stalls

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

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

  1. Start the Windows Codex desktop app.
  2. Run a task that creates or iterates on a rich interactive HTML presentation.
  3. Ask Codex to render/inspect the page and validate desktop/mobile layout and interactions using browser or Playwright-based checks.
  4. Repeat several iterations, including interaction and responsive-layout validation.
  5. After the task reports completion, continue using the desktop app and other Windows applications.
  6. Observe severe system-wide UI and mouse stutter. Fully exit the desktop app and observe that responsiveness returns.

Observed process behavior

  • codex.exe runs the shared local app-server and owns codex-code-mode-host.exe.
  • node_repl.exe processes from the bundled cua_node runtime appear as direct children of the same app-server process.
  • The node_repl.exe count reached 37 during the affected session.
  • After the HTML task became idle/completed, 21 node_repl.exe processes plus codex-code-mode-host.exe were 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_repl workers 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.

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 13 days ago

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

  • #38614
  • #38526
  • #38079

Powered by Codex Action

ppg94 · 13 days ago

Additional Windows reproduction: generated config returned, then 24 workers accumulated

I reproduced this independently on Windows 11 (10.0.26200) with Codex Desktop 26.810.6296.0.

A previous workaround had commented out the global node_repl MCP block. After restarting Codex, the Desktop/plugin runtime generated an active [mcp_servers.node_repl] block in config.toml again. 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:

  • 24 live node_repl.exe processes, all direct children of the same codex.exe app-server.
  • Start times were spread across the session and tracked subsequent tool activity rather than one startup burst.
  • The 24 workers accounted for 871 threads, 3,605 handles, and about 228 MiB working set.
  • Most workers had 36 threads each; several had 38-39.
  • The broader Desktop/app-server snapshot had more than 1,100 related threads while the whole Windows UI was stuttering severely.

I then terminated exactly those 24 workers:

  • node_repl.exe: 24 -> 0
  • The 871 worker threads and 3,605 worker handles disappeared immediately.
  • In the previous identical recurrence, terminating 16 accumulated workers immediately restored normal whole-system responsiveness; disabling the MCP block then prevented recurrence until the generated block was restored.

After commenting out the regenerated block again, codex mcp list parsed successfully and listed no node_repl server. 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.exe sustained 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.

ppg94 · 13 days ago

Additional lifecycle/config observation: generated block returns even when related plugins are disabled

After a full Desktop restart with bundled chrome, browser, and computer-use plugins explicitly set to enabled = false, Desktop still regenerated an active [mcp_servers.node_repl] block and spawned 5 direct node_repl.exe workers within minutes.

Using the documented MCP setting below was more durable than commenting/removing the generated block:

[mcp_servers.node_repl]
enabled = false

After adding that field:

  • codex mcp list reported node_repl as disabled;
  • the 5 existing workers were terminated;
  • worker count remained 0 during the immediate follow-up;
  • the generated command/environment block remained present, so Desktop did not need to reconstruct missing configuration.

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 = false override and must not spawn the server when that override is present.

No session content, account details, usernames, local paths, or raw logs are attached.

smigolsmigol · 12 days ago

Additional source-level evidence from affected Windows Desktop build 26.810.4967.0 narrows the worker-retirement failure:

  • The desktop owner-retirement policy sets a one-hour inactivity TTL and a maximum of four inactive owner tasks.
  • It calculates how many owners exceed that maximum, but the returned unsubscribe candidates contain only TTL-expired IDs. The four-owner cap is therefore not enforced.
  • Tasks marked active or inProgress are excluded from TTL retirement. Stale task state can keep a runtime alive indefinitely.
  • In the affected session, 11 successful inactive-task unsubscribes reduced repeated per-task helper sets from 21 to 17. The oldest remaining repeated helper was nearly 14 hours old. No unsubscribe RPC failure or shutdown timeout was recorded.

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. active and inProgress state 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.