Claude desktop app leaks PTYs, exhausting system-wide kern.tty.ptmx_max (forkpty: Device not configured)
Summary
The Claude desktop app (/Applications/Claude.app) leaks pseudo-terminal master file descriptors over time. After ~1.5 days of uptime the app process held 509 open /dev/ptmx handles, which is essentially the entire macOS default PTY pool (kern.tty.ptmx_max = 511). Once the pool is exhausted, no application on the machine can allocate a new PTY — new terminal tabs, SSH sessions, tmux, etc. fail with:
[forkpty: Device not configured]
[Could not create a new process and open a pseudo-tty.]
This is a system-wide impact, not limited to Claude itself.
Environment
- Claude desktop app: 1.11847.5
- Claude Code (embedded): 2.1.170
- macOS: 26.5 (build 25F71) — Darwin 25.5.0
- Hardware: Apple Silicon / macOS
Evidence
Process tree (the leaking process is the GUI app, which is the parent of the Claude Code session):
PID 93684 /Applications/Claude.app/Contents/MacOS/Claude (uptime 1d 14h)
└─ claude-code 2.1.170
└─ zsh (Bash tool sessions)
/dev/ptmx handles per process:
$ lsof /dev/ptmx | awk 'NR>1{print $1}' | sort | uniq -c | sort -rn
509 Claude
1 Terminal
1 Code H
The 509 FDs are character-device handles on /dev/ptmx, each a distinct PTY master:
$ lsof -p 93684 | grep -i ptmx | head -3
Claude 93684 tonywang 39u CHR 15,20 0t0 605 /dev/ptmx
Claude 93684 tonywang 42u CHR 15,0 0t0 605 /dev/ptmx
Claude 93684 tonywang 43u CHR 15,49 0t0 605 /dev/ptmx
$ lsof -p 93684 | grep -c -i ptmx
509
PTY pool state:
$ sysctl kern.tty.ptmx_max
kern.tty.ptmx_max: 511 # default
509 of 511 consumed by a single Claude.app process.
Likely cause
PTY master FDs allocated for shell/Bash-tool invocations (or terminal sessions) are not being closed/reaped when those child processes exit. The count grows monotonically with app uptime and usage, consistent with an FD leak rather than legitimate concurrent use (there were not 509 live shells).
Impact
- Eventually breaks all new pseudo-terminal allocation system-wide (new Terminal tabs, SSH, tmux, screen, IDE integrated terminals).
- Self-inflicted on Claude Code too: its own
Bashtool can't spawn interactive PTYs once the pool is full. - Only recovers by quitting Claude.app (releases all leaked FDs) or raising
kern.tty.ptmx_max.
Reproduction
- Run the Claude desktop app for an extended period (~1+ day), using Claude Code / Bash tooling normally.
- Periodically check:
lsof /dev/ptmx | grep -c Claude— the count climbs steadily and does not fall after shells exit. - When it approaches
kern.tty.ptmx_max, opening any new terminal/SSH session fails withforkpty: Device not configured.
Workarounds
- Temporary:
sudo sysctl -w kern.tty.ptmx_max=999(kernel hard max) to add headroom. - Full reset: quit and reopen the Claude desktop app to release the leaked FDs.
Expected behavior
PTY master FDs should be closed when the associated shell/child process terminates, so the open-/dev/ptmx count stays roughly proportional to currently-live shells rather than growing for the lifetime of the app.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗