PTY master fd leak in Claude desktop app exhausts macOS kern.tty.ptmx_max after ~2-3 days

Resolved 💬 2 comments Opened May 28, 2026 by jonbcampos-alto Closed Jun 22, 2026

Summary

After 2–3 days of normal use, the Claude desktop app on macOS accumulates /dev/ptmx master file descriptors that are never released. Once the open count hits the kernel cap (kern.tty.ptmx_max, default 511), every subsequent forkpty() on the system fails — including the user's Terminal.app, iTerm2, tmux, ssh, script, etc. — with:

forkpty: Device not configured
Could not create a new process and open a pseudo-tty.

Quitting and relaunching Claude.app releases all the leaked fds, confirming the leak is in the long-lived desktop process (not in spawned CLI subprocesses).

Repro

  1. Launch Claude.app on macOS.
  2. Use Claude Code from within it normally over several days (open/close sessions, run Bash tool calls, etc.).
  3. Eventually any new terminal or pty-using program on the system fails with the forkpty: Device not configured error above.

Diagnostic data from my machine

Captured live while the system was at the cap:

$ sysctl kern.tty.ptmx_max
kern.tty.ptmx_max: 511

$ lsof /dev/ptmx 2>/dev/null | wc -l
512        # 511 open + 1 header line — exactly at the kernel cap

$ lsof /dev/ptmx 2>/dev/null | awk 'NR>1 {print $1, $2}' | sort | uniq -c | sort -rn
 510 Claude 1650
   1 Terminal 1656

$ ps -p 1650 -o pid,etime,comm,args
  PID     ELAPSED COMM             ARGS
 1650 02-23:07:56 /Applications/Cl /Applications/Claude.app/Contents/MacOS/Claude

PID 1650 is the main Claude desktop binary (/Applications/Claude.app/Contents/MacOS/Claude), uptime ~2d 23h, holding 510 of the 511 available master pty fds. The CLI subprocesses (claude.app/Contents/MacOS/claude — six of them currently active) account for none of the leaked fds; the leak is in the parent.

The 510 figure scales roughly with the number of Claude Code sessions spawned over the app's lifetime, so I suspect each Code session that the desktop app spawns leaks one master pty fd on the parent side (the slave is presumably closed when the session exits, but the master fd in the desktop process is retained).

Environment

  • Claude desktop: 1.8555.0
  • macOS: 15.7.7 (24G720), Apple Silicon
  • App uptime when reproduced: ~2 days 23 hours
  • Number of Claude Code sessions opened over that window: many (dozens)

Impact

The failure is system-wide, not contained to Claude. Once Claude.app holds all the ptys, the user cannot open a new shell anywhere — including outside Claude Code — until they quit Claude or reboot. This makes it very disruptive: people typically hit it mid-workflow with no obvious connection to Claude being the cause.

Workaround

Quit Claude.app (or kill <pid-of-Claude-main>) instantly returns the system to a healthy state. No reboot necessary. But this also kills any in-progress Claude Code sessions, so it's not a silent fix.

Suspected cause

Wherever the desktop app spawns Claude Code as a child via posix_openpt / forkpty, the master fd is not being closed when the child session ends. The slave side appears to close fine (no leaked /dev/ttys* holders in lsof), but the master fd accumulates in the desktop process.

A quick check would be to instrument the spawn path to log master-fd open/close pairs and confirm they don't balance over a session's lifetime.

Happy to provide more lsof / fs_usage / sample dumps from PID 1650 if useful.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗