Repeat `Os { code: 24, kind: Uncategorized, message: "Too many open files" }` crashes
What version of Codex CLI is running?
v0.120.0
What subscription do you have?
Pro
Which model were you using?
gpt-5.4 xhigh
What platform is your computer?
Darwin 25.4.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
Ghostty 1.3.1
What issue are you seeing?
This has been going on for a month-ish or more, despite several updates to codex that I'd hoped would resolve it without needing to file an issue of my own.
The crashes are almost always in https://github.com/openai/codex/blob/b3ae531b3a6c4f9742dff6a7bd1b14796bde9c53/codex-rs/protocol/src/permissions.rs#L1020
The rust panic! looks like this with RUST_BACKTRACE=1:
```codex-tui
› The application panicked (crashed).
Message: /tmp is absolute: Os { code: 24, kind: Uncategorized, message: "Too many open files" }
Location: protocol/src/permissions.rs:1057ee-worktree-specmaxxing · Context [██▏ ] · 5h 97% · weekly 49% · 950K window · 34.9M used · 34.8M in · 111K out · Fast on · Main [default]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
2: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
3: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
4: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
5: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
6: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
7: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
8: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
9: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
10: __ZN4absl22internal_any_invocable19LocalManagerTrivialENS0_14FunctionToCallEPNS0_15TypeErasedStateES3_<unknown>
at <unknown source file>:<unknown line>
11: __ZN4absl22internal_any_invocable19LocalManagerTrivialENS0_14FunctionToCallEPNS0_15TypeErasedStateES3_<unknown>
at <unknown source file>:<unknown line>
12: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
13: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
14: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
15: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
16: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
17: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
18: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
19: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
20: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
21: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
22: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
23: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
24: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
25: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
26: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
27: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
28: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
29: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
30: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
31: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
32: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
33: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
34: __pthread_cond_wait<unknown>
at <unknown source file>:<unknown line>
Run with COLORBT_SHOW_HIDDEN=1 environment variable to disable frame filtering.
Run with RUST_BACKTRACE=full to include source snippets.
Warning: SpanTrace capture is Unsupported.
Ensure that you've setup a tracing-error ErrorLayer and the semver versions are compatible
The application panicked (crashed).
Message: cwd root must be an absolute path: Too many open files (os error 24)
Location: protocol/src/permissions.rs:1021
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
2: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
3: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
4: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
5: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
6: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
7: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
8: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
9: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
10: __ZN4absl22internal_any_invocable19LocalManagerTrivialENS0_14FunctionToCallEPNS0_15TypeErasedStateES3_<unknown>
at <unknown source file>:<unknown line>
11: __ZN4absl22internal_any_invocable19LocalManagerTrivialENS0_14FunctionToCallEPNS0_15TypeErasedStateES3_<unknown>
at <unknown source file>:<unknown line>
12: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
13: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
14: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
15: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
16: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
17: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
18: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
19: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
20: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
21: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
22: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
23: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
24: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
25: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
26: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
27: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
28: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
29: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
30: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
31: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
32: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
33: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
34: __mh_execute_header<unknown>
at <unknown source file>:<unknown line>
35: __pthread_cond_wait<unknown>
at <unknown source file>:<unknown line>
Run with COLORBT_SHOW_HIDDEN=1 environment variable to disable frame filtering.
Run with RUST_BACKTRACE=full to include source snippets.
Warning: SpanTrace capture is Unsupported.
Ensure that you've setup a tracing-error ErrorLayer and the semver versions are compatible
^C^X^C^Czsh: terminated codex resume
Exit status: 143
Not super useful of course, as is what I'd expect with a native crash. If necessary, I can probably use lldb to actually get something useful.
When we hit the *crash*, the TUI gets fully corrupted, and I have to quit the binary from activity monitor.
HOWEVER, there are also paths where the `codex` CLI doesn't crash, and the error makes it to the model... If I explicitly tell codex to plan for this bug before we begin work, it usually allows us to gently pause work and relaunch, after it notifies me as such:
```codex-tui
We hit the file-descriptor bug again: a fresh local read just failed with Too many open files (os error 24), so I’m stopping here instead of pushing forward in a confused state.
It sometimes seems like the crash condition only happens when subagents are running, but I'm not quite sure.
What steps can reproduce the bug?
Uploaded thread: 019d8b31-ed1e-7a33-8511-d5536fddc1e8
Otherwise I'm not really sure, if this was a reasonable bug I'd assume most other people would be hitting it in daily use with moderately long running sessions
What is the expected behavior?
Not.... leaking file descriptors?
Additional information
Surely there's a way in rust to somehow enforce file handle usage and freeing at compile time?
Back in my C++ Windows days, a clever hack I came up with that I used to use a lot was declaring HANDLEs to the static analyzer as if they were pointers freed by CloseHandle and similar functions. It worked in part because of the C roots of Windows, where HANDLEs are just typedefd void* under the hood, and the MSVC static analyzer had reasonably good modeling of free and similar function semantics to detect memory bugs.
7 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Thanks for reporting this. I don't think think this has been reported by any other users (either internally to OpenAI or externally). That might mean that it's specific to your system configuration. This sort of problem can sometimes be caused by antivirus software, so that's something you might want to check.
That would make sense! I'm not running any third party security software though. Any pointers and tips on what I should do to help debug this? Debug logs and env vars?
Odd, just hit it in a new place too:
https://github.com/openai/codex/blob/cdfcd2ca9268adbd4bd3ba5af527c97fa8a82805/codex-rs/core/src/plugins/store.rs#L33
Follow-up from Codex (GPT-5.4 xhigh), posting on behalf of @ariccio. Alexander asked me to keep this concise. I reproduced/observed this by running
codex-cli 0.121.0in a longcodex resumeterminal session with stdio MCP enabled and parallel subagents.This no longer looks like antivirus or generic host configuration. The live terminal Codex process hit
250FDs under the default macOS soft limit of256:164pipe FDs,48SQLite FDs,14sockets, and54direct MCP-like child processes. Each subagent/worker start correlated by timestamp with a fresh stdio MCP bundle under the root Codex PID (mongodb-mcp-server,@google-cloud/observability-mcp,xcodebuildmcp,@kimsungwhee/apple-docs-mcp). Several correspondingthread_spawn_edgesrows were alreadyclosed, but the MCP children and parent-held stdin/stdout/stderr pipe ends were still alive.Important correction:
#10710is in0.121.0(git merge-base --is-ancestor 82c981caf rust-v0.121.0succeeds). So the missing piece is not the low-level process-group guard. The practical model is:wait_agentfinal status such asCompletedis not shutdown; the session can still retain itsMcpConnectionManager.close_agentsubmitsOp::Shutdown, then removes the thread fromThreadManagerStateand releases the spawn slot without waiting forShutdownComplete/session_loop_termination.Session/ RMCP-client drop.NotFoundwhile its stdio MCP clients are still alive. Then#10710never runs because the transport was not dropped.os error 24causes tool failures, panics, or softlock.Related upstream threads:
close_agent/ core subagent teardownMost useful fix direction from this reproduction: make
close_agenta bounded teardown barrier. It should interrupt if needed, call ashutdown_and_wait-style path, remove/release the thread only after shutdown completion, and return a timeout/failure while keeping the thread reachable if teardown does not complete. Also consider explicit MCP-manager shutdown/drain during core session shutdown, plus a regression test that closes a subagent with a stdio MCP server and asserts the MCP process group is gone when close returns.I'm having this issue too, subagent-opened file descriptors and MCP connector processes aren't being killed when Codex closes the subagents.
Has been resolved for a few weeks