Claude desktop app leaks /dev/ptmx master fds, exhausting the OS pty pool (forkpty: Device not configured)
Claude desktop app leaks /dev/ptmx master fds, exhausting the OS pty pool (forkpty: Device not configured)
Summary
The Claude desktop app (/Applications/Claude.app) continuously leaks pseudo-terminal master file descriptors (/dev/ptmx) from background activity. Over a long-running session it accumulates hundreds of orphaned masters and exhausts the macOS system pty cap (kern.tty.ptmx_max, default 511). Once exhausted, no process on the machine can allocate a new pty — Terminal.app, iTerm, and VS Code's integrated terminal all fail to open 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.
Environment
- macOS 26.2 (25C56), Apple Silicon (arm64), Darwin 25.2.0
- Claude desktop app 1.11847.5
- Embedded Claude Code 2.1.170
- App uptime at observation: ~20h; several MCP servers connected
Evidence (directly measured)
kern.tty.ptmx_max default is 511. The app held more masters than that:
$ lsof -p <Claude.app PID> | grep -c /dev/ptmx
519 # then 540, 560, 563, 565 on successive reads — monotonically increasing
Masters vastly exceed actual live shells:
ptmx masters held by Claude.app : 565
live pty slaves (zsh/bash/login) : 12 # ~553 orphaned masters
fd numbers are sparse across the whole process lifetime (47u … 1784u, all CHR /dev/ptmx) — the fingerprint of fds opened and never closed.
The leak is time/background-driven, NOT per-command. Controlled tests:
- 6 agent shell-spawning commands in a row → master count unchanged (560 → 560). Rules out "one leak per spawned shell."
- A 12-second pure idle wait (no commands, no shells spawned) → 560 → 563 (+3), ~15 masters/min. The leak advances with wall-clock time from internal background activity.
Reproduction of the user-visible failure once the pool is exhausted:
import os
for i in range(12):
os.openpty() # OSError: [Errno 6] Device not configured (at the first call, when cap is reached)
Impact
- All pty-allocating apps system-wide stop opening terminals once the cap is hit.
- Slow-building (hours), so it surfaces as a confusing "my terminal suddenly won't open anything" with no obvious cause.
Workarounds (not fixes)
- Quit and relaunch Claude.app — releases all leaked masters immediately; pool returns to normal. No reboot needed.
- Temporary headroom:
sudo sysctl -w kern.tty.ptmx_max=999(max allowed value; resets on reboot).
Expected
Background pty masters opened by the app should be closed when their session ends; steady-state master count should track live sessions, not grow unbounded with uptime.
Ask
Please audit where Claude.app opens /dev/ptmx from periodic/background activity and ensure the master fd is closed. The ~15/min idle rate suggests a recurring timer/poll that opens a pty per tick without releasing it.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗