Claude desktop app leaks /dev/ptmx master fds, exhausting the OS pty pool (forkpty: Device not configured)

Resolved 💬 2 comments Opened Jun 12, 2026 by dumko2001 Closed Jun 22, 2026

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.

View original on GitHub ↗

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