[Bug]: Codex Desktop on Windows retains one context-mode MCP server per task; cache cleanup hits os error 32
Platform
Codex CLI — Codex Desktop on Windows, using its long-lived app-server backend.
context-mode version
1.0.169 (also confirmed as npm latest when this report was prepared).
Summary
During normal multi-task use of Codex Desktop on Windows, context-mode MCP processes accumulated under one long-lived Codex parent instead of returning to baseline when tasks became inactive or completed.
The first process-tree snapshot found 29 context-mode start.mjs processes with approximately 8.5 GiB summed working set. Summed working set can double-count shared pages, but the process count and persistent per-process footprint were independently significant. The machine was extremely slow and showed sustained disk writes around 50 MB/s at the time.
Other Codex MCP/plugin runtimes also accumulated in roughly the same 30-set pattern (Sites, Data Analytics, and node_repl). This suggests the primary per-task lifecycle defect is likely host-owned rather than a heap leak inside one context-mode process. This report is filed here because context-mode can still improve Codex/Windows diagnostics and provide safe targeted pre-removal cleanup for its own processes.
The context-mode state under ~/.codex/context-mode was 3.21 GiB. The installed plugin/cache was removed after collecting process evidence; the state directory was preserved.
Debug script output (REQUIRED)
The official script was run from the latest 1.0.169 checkout immediately after the retained processes were terminated and the Codex plugin was removed, because restoring the machine was the first priority. Thus Running context-mode processes: 0 and Install method: git clone / manual describe the post-cleanup run; pre-cleanup evidence is below. User paths and the hostname were normalized, and config contents are null.
{
"version": "2.0.0",
"generated": "2026-07-13T14:15:00Z",
"sections": {
"1. System Info": {
"checks": [],
"info": {
"OS type": "windows",
"uname -a": "MINGW64_NT-10.0-26200 <host> 3.6.4-b9f03e96.x86_64 2025-07-16 18:17 UTC x86_64 Msys",
"Architecture": "x86_64",
"Windows ver": "Microsoft Windows [Version 10.0.26200.8737]",
"Shell": "/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe",
"Bash version": "5.2.37(1)-release",
"Locale": "LANG=unset, LC_ALL=unset"
},
"configs": [],
"warnings": [],
"details": []
},
"2. Runtime Versions": {
"checks": [],
"info": {
"Node.js": "v24.13.0",
"node path": "/c/Program Files/nodejs/node",
"execPath": "C:\\Program Files\\nodejs\\node.exe",
"Node install method": "unknown",
"Bun": "1.3.14",
"bun path": "~/.bun/bin/bun",
"Codex CLI": "codex-cli 0.144.1",
"Python": "Python 3.14.4",
"npm": "11.6.2",
"npm global root": "~\\AppData\\Roaming\\npm\\node_modules"
},
"configs": [],
"warnings": [
"Codex ≥0.118.0: exec-mode MCP broken (openai/codex#16685). Pin to ≤0.116.0 for exec-mode."
],
"details": []
},
"3. context-mode Installation": {
"checks": [
{
"pass": false,
"label": "build/ directory exists"
},
{
"pass": true,
"label": "hooks/pretooluse.mjs exists"
},
{
"pass": true,
"label": "hooks/sessionstart.mjs exists"
},
{
"pass": true,
"label": "server.bundle.mjs exists"
},
{
"pass": true,
"label": "cli.bundle.mjs exists"
}
],
"info": {
"Installed version": "1.0.169",
"Plugin root": "<diagnostic-clone>",
"Install method": "git clone / manual",
"npm latest": "1.0.169"
},
"configs": [],
"warnings": [],
"details": []
},
"4. better-sqlite3 Native Module": {
"checks": [
{
"pass": true,
"label": "better-sqlite3 .node binary exists"
},
{
"pass": true,
"label": "require('better-sqlite3') succeeds"
},
{
"pass": true,
"label": "npm ignore-scripts is false"
}
],
"info": {
"Binary path": "<diagnostic-clone>/node_modules/better-sqlite3/build/Release/better_sqlite3.abi137.node",
"Node ABI version": "137"
},
"configs": [],
"warnings": [],
"details": []
},
"5. Adapter Detection": {
"checks": [],
"info": {
"Active adapter (env)": "codex",
"Installed adapters": "claude-code codex gemini-cli openclaw kiro opencode"
},
"configs": [],
"warnings": [],
"details": []
},
"6. Config Files": {
"checks": [],
"info": {
"Claude settings.json": "~/.claude/settings.json (exists)",
"Claude settings.local.json": "~/.claude/settings.local.json (exists)",
"Gemini settings.json": "~/.gemini/settings.json (exists)",
"Codex config.toml": "~/.codex/config.toml (exists)",
"Codex hooks.json": "~/.codex/hooks.json (not found)",
"Cursor hooks.json (project)": "<diagnostic-clone>/.cursor/hooks.json (not found)",
"Cursor mcp.json (project)": "<diagnostic-clone>/.cursor/mcp.json (not found)",
"Cursor mcp.json (global)": "~/.cursor/mcp.json (not found)",
"Cursor hooks.json (global)": "~/.cursor/hooks.json (not found)",
"VS Code mcp.json (project)": "<diagnostic-clone>/.vscode/mcp.json (not found)",
"opencode.json (project)": "<diagnostic-clone>/opencode.json (not found)",
"opencode.json (dotdir)": "<diagnostic-clone>/.opencode/opencode.json (not found)",
"opencode.json (global)": "~/.config/opencode/opencode.json (exists)",
"KiloCode settings.json": "~/.config/kilo/settings.json (not found)",
"OpenClaw openclaw.json": "~/.openclaw/openclaw.json (not found)",
"Kiro mcp.json": "~/.kiro/settings/mcp.json (exists)",
"Kiro default agent": "~/.kiro/agents/default.json (not found)",
"Zed settings.json": "~/.config/zed/settings.json (not found)"
},
"configs": [
{
"name": "Claude settings.json",
"path": "~/.claude/settings.json",
"exists": true,
"content": null
},
{
"name": "Claude settings.local.json",
"path": "~/.claude/settings.local.json",
"exists": true,
"content": null
},
{
"name": "Gemini settings.json",
"path": "~/.gemini/settings.json",
"exists": true,
"content": null
},
{
"name": "Codex config.toml",
"path": "~/.codex/config.toml",
"exists": true,
"content": null
},
{
"name": "opencode.json (global)",
"path": "~/.config/opencode/opencode.json",
"exists": true,
"content": null
},
{
"name": "Kiro mcp.json",
"path": "~/.kiro/settings/mcp.json",
"exists": true,
"content": null
}
],
"warnings": [],
"details": []
},
"7. Hook Validation": {
"checks": [
{
"pass": true,
"label": "No stale hook paths in Claude settings.json"
},
{
"pass": true,
"label": "PreToolUse registered"
},
{
"pass": true,
"label": "PostToolUse registered"
},
{
"pass": true,
"label": "PreCompact registered"
},
{
"pass": true,
"label": "SessionStart registered"
},
{
"pass": true,
"label": "No backslash paths in settings.json"
}
],
"info": {},
"configs": [],
"warnings": [],
"details": []
},
"8. SQLite / FTS5 Test": {
"checks": [
{
"pass": true,
"label": "FTS5 in-memory test"
}
],
"info": {},
"configs": [],
"warnings": [],
"details": []
},
"9. Executor Test": {
"checks": [
{
"pass": true,
"label": "node subprocess spawn"
},
{
"pass": true,
"label": "bash subprocess spawn"
}
],
"info": {},
"configs": [],
"warnings": [],
"details": []
},
"10. Process Check": {
"checks": [],
"info": {
"Running context-mode processes": "0"
},
"configs": [],
"warnings": [],
"details": []
},
"11. Session Databases": {
"checks": [],
"info": {
"~/.claude/context-mode/sessions": "38 files, 2.2M",
"~/.codex/context-mode/sessions": "13 files, 165M",
"~/.gemini/context-mode/sessions": "37 files, 2.1M",
"~/.kiro/context-mode/sessions": "4 files, 216K",
"Total session DBs": "92"
},
"configs": [],
"warnings": [],
"details": []
},
"12. Environment Variables": {
"checks": [],
"info": {
"TMPDIR": "/c/tmp/context-mode-debug",
"TEMP": "/tmp",
"TMP": "/tmp",
"NODE_OPTIONS": "unset",
"NODE_PATH": "<diagnostic-clone>/node_modules:<diagnostic-clone>/node_modules:",
"NODE_EXTRA_CA_CERTS": "unset",
"SSL_CERT_FILE": "unset",
"CURL_CA_BUNDLE": "unset",
"SSH_AUTH_SOCK": "unset",
"CONTEXT_MODE_SESSION_SUFFIX": "unset",
"CONTEXT_MODE_NODE": "unset"
},
"configs": [],
"warnings": [],
"details": []
},
"13. Hook Execution": {
"checks": [
{
"pass": true,
"label": "PreToolUse denies WebFetch"
},
{
"pass": true,
"label": "PreToolUse passes Write tool through"
},
{
"pass": true,
"label": "SessionStart injects routing context"
}
],
"info": {},
"configs": [],
"warnings": [],
"details": []
},
"14. MCP Server Startup": {
"checks": [
{
"pass": true,
"label": "Server entry + deps resolve"
}
],
"info": {},
"configs": [],
"warnings": [],
"details": []
},
"15. SQLite Concurrency": {
"checks": [
{
"pass": false,
"label": "Session DB uses WAL mode"
},
{
"pass": true,
"label": "No oversized WAL journals (>1MB)"
},
{
"pass": true,
"label": "No orphaned -shm files"
},
{
"pass": true,
"label": "Concurrent SQLite writes (3 conns × 30)"
}
],
"info": {},
"configs": [],
"warnings": [],
"details": []
},
"17. Sandbox Environment": {
"checks": [
{
"pass": false,
"label": "System CA certificates found"
},
{
"pass": true,
"label": "Temp dir writable"
},
{
"pass": true,
"label": "Env denylist strips dangerous vars"
}
],
"info": {
"Effective temp dir": "/c/tmp/context-mode-debug"
},
"configs": [],
"warnings": [],
"details": []
},
"18. Network / TLS": {
"checks": [
{
"pass": true,
"label": "HTTPS to npm registry"
},
{
"pass": true,
"label": "Temp dir >100MB free"
}
],
"info": {},
"configs": [],
"warnings": [],
"details": []
}
},
"summary": {
"pass": 27,
"fail": 3,
"warnings": 1,
"total": 30
}
}Exact prompt that triggered the bug (REQUIRED)
This is the literal first message in the task where the retained-process investigation began:
코덱스 프로세스가 느려지는 원인 파악을 해보자. 컨트리뷰션 포인트가 있을지 살펴보자. 누수되는 램이 있나?The process fan-out occurs during task initialization and was not dependent on a particular ctx_* call.
Full error output (REQUIRED)
Command: codex plugin remove context-mode@context-mode --json
Complete output (the CLI did not print the locked path):
Error: failed to remove existing plugin cache entry: 다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다. (os error 32)
Caused by:
0: failed to remove existing plugin cache entry: 다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다. (os error 32)
1: 다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스 할 수 없습니다. (os error 32)English meaning: the process cannot access the file because another process is using it.
Steps to reproduce (REQUIRED)
- Install and enable context-mode
1.0.169through the Codex plugin manager on Windows, then restart Codex Desktop. - Keep Codex Desktop/app-server alive and create/complete multiple normal Codex tasks over time.
- Inspect direct Node children of the long-lived Codex parent. Here context-mode was launched as
node ./start.mjs, so searching only for literalcontext-modemisses it. - Observe whether additional
./start.mjschildren appear with task creation times and remain after the tasks become inactive/completed. - Compare other MCP/plugin children of the same Codex parent. Sites, Data Analytics, and node_repl showed the same per-task pattern here.
- Run
codex plugin remove context-mode@context-mode --jsonwhile retained./start.mjschildren exist. - Observe Windows
os error 32during plugin-cache deletion. - Terminate only verified context-mode PIDs and retry the same command. It succeeds.
Expected behavior
- Completed/inactive Codex tasks release their context-mode MCP process, or the host reuses a bounded runtime.
- Codex-local context-mode cache files are not held open after the owning task is done.
- Removal through the Codex plugin manager succeeds without manual process termination.
- context-mode diagnostics identify Codex-launched relative
./start.mjsprocesses and their owning Codex parent.
Actual behavior
- Initial snapshot: 29 retained context-mode
start.mjsprocesses, approximately 8.5 GiB summed working set. - After an earlier cleanup, three new
node ./start.mjsprocesses appeared at different task creation times under the same Codex parent. - Plugin removal failed twice with
os error 32while those three processes were alive. - Searching command lines for
context-modereturned no match because Codex used relative./start.mjs. - After terminating the three verified PIDs, plugin removal succeeded and the Codex-local marketplace/cache could be removed.
- Other MCP/plugin runtimes accumulated too, so the main lifecycle defect likely belongs to Codex app-server. The same evidence was posted to OpenAI: https://github.com/openai/codex/issues/31499#issuecomment-4958216247
What have you tried to fix it?
- Confirmed
1.0.169was both the installed version and npm latest. - Inspected the Codex app-server descendant tree and correlated creation times with task starts.
- Distinguished a context-mode-only heap leak from host-owned MCP fan-out by checking other plugin runtimes.
- Searched existing issues. The closest is #565 (OpenCode retains one child per session), but none covered Codex Desktop + Windows + relative
./start.mjs+ cache-removalos error 32. - Stopped only verified context-mode PIDs and retried the supported removal command; it succeeded.
- Removed the Codex-only plugin and marketplace registration. The global npm installation and other hosts were left untouched.
Operating System
Windows (PowerShell); Windows build 10.0.26200.8737.
JS Runtime
Node v24.13.0; Bun 1.3.14; Codex CLI 0.144.1.
Pre-submission checklist
- I have run the debug script and pasted the output above.
- I am using the latest version of context-mode.
- I have searched existing issues for duplicates.
- I have included steps to reproduce the issue.
Source: mksglu/context-mode