macOS desktop app leaks PTY file descriptors, breaks all terminal apps system-wide after ~1 day
Summary
The macOS Claude desktop app leaks pseudo-terminal (PTY) file descriptors over time. After ~28 hours of uptime, a single Claude.app process was holding 509 open PTY master fds (/dev/ptmx), which exhausted the macOS default kern.tty.ptmx_max limit of 511. Every other terminal app on the system then fails to launch with:
The terminal process failed to launch: A native exception occurred during launch (posix_openpt failed: Device not configured).
The user cannot open VS Code terminals, iTerm tabs, Terminal.app windows, etc. until they quit Claude.app or raise the kernel limit.
Environment
- Claude.app version: 1.8089.1
- Embedded claude-code version: 2.1.142
- macOS: 26.4.1 (build 25E253), arm64
- Darwin kernel: 25.4.0
Reproduction
- Launch Claude.app, run a Claude Code session inside it.
- Leave the app running for an extended period (~1+ day in our case) with normal usage — spawning Bash tool calls, subagents, etc.
- Observe
lsof /dev/ptmx | awk '$1=="Claude"' | wc -lgrow steadily and never shrink. - Once the count nears
sysctl kern.tty.ptmx_max(default 511), all PTY allocation on the system breaks.
Evidence
$ lsof /dev/ptmx | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn
509 Claude
2 iTerm2
$ sysctl kern.tty.ptmx_max
kern.tty.ptmx_max: 511
$ ls /dev/ttys* | wc -l
527
$ ps -p <claude-pid> -o pid,etime,command
PID ELAPSED COMMAND
89142 01-04:14:16 /Applications/Claude.app/Contents/MacOS/Claude
That's ~509 PTYs leaked over ~28 hours of normal use, i.e. ~18 leaked per hour. Only 2 of the open PTYs map to currently-running child processes — the rest have no associated process and appear to be orphaned master fds from completed Bash tool calls / subagents that the app never closed.
Impact
- Hard system-wide failure: no terminal app can open new sessions, including VS Code, iTerm, Terminal.app, Warp.
- The user cannot diagnose or fix the problem without already-open terminal access; they were unblocked only by running
sysctl -w kern.tty.ptmx_max=999through the still-running Claude Code session itself. - Reboot or quitting Claude.app is the only durable fix; the leak resumes on relaunch.
Workaround
sudo sysctl -w kern.tty.ptmx_max=999 # buys headroom, resets at reboot
Or quit Claude.app entirely.
Likely cause
PTY master fds opened for child tool processes (Bash invocations, subagent spawns, MCP server stdio pipes, etc.) are not being closed on child exit. Each Bash tool call presumably allocates a PTY; over a day of agent activity that's hundreds of fds.
Worth auditing the child-process spawn path in the desktop app's claude-code embedding for missing close() on the master fd after the child reaps.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗