[BUG] TUI completely freezes input at high message counts (250+) — ioctl TIOCSWINSZ loop starves event loop on Linux/NixOS

Resolved 💬 8 comments Opened Apr 9, 2026 by randomizedcoder Closed May 24, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

During long agentic sessions, the TUI becomes completely unresponsive — no keyboard input accepted (Enter, Escape, number keys, Ctrl+C all ignored). The process stays alive but is frozen. Only recovery is kill from another terminal.

Occurs when an approval prompt appears while background bash commands are still streaming output simultaneously.

Diagnostic evidence — at moment of freeze:

Debug log shows useDeferredValue message count climbing to 250+:

[useDeferredValue] Messages deferred by 1 (249→250)
[useDeferredValue] Messages deferred by 1 (250→251)

Followed by

Getting matching hook commands for Notification with query: permission_prompt

Then the permission_prompt notification fires and the log goes silent. Input never works again.

Frozen process syscall (sudo cat /proc/$PID/syscall):

16 0x16 0x402c542c 0x7ffef19315f0 0x2a015d800011 0x0 0x2 0x7ffef19315f0 0x7ff7c7d19748

Syscall 16 = ioctl with TIOCSWINSZ — the TUI renderer is stuck in a terminal resize loop, never returning control to the event loop to process keyboard input.

All threads show the same pattern when frozen — constant full-screen rewrites with zero blits, consistent with the render pathology described in #25286.

Additionally, ~/.claude.json is being atomically rewritten dozens of times per second (~every 5ms) at the moment of freeze, adding further I/O pressure to the event loop.

2026-03-12T16:43:31.648Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:31.652Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:31.658Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:31.661Z [DEBUG] File /home/das/.claude.json written atomically
...

Related: #25286 (same renderer pathology on macOS) — this is a Linux/NixOS confirmation with more detailed diagnostics.

Root cause hypothesis
At ~250+ messages, the React-based TUI renderer enters a pathological state where:

  1. It defers messages faster than it can process them (useDeferredValue count climbs unbounded)
  2. The terminal renderer does constant full-screen rewrites (ioctl TIOCSWINSZ loop)
  3. These together starve the Node.js event loop of cycles needed to process keyboard input
  4. ~/.claude.json is simultaneously being written dozens of times/second, adding further I/O pressure

What Should Happen?

Keyboard input should remain responsive regardless of message count or concurrent background command activity. The TUI renderer should be debounced/rate-limited to prevent event loop starvation.

Error Messages/Logs

2026-03-12T16:43:39.707Z [DEBUG] [useDeferredValue] Messages deferred by 1 (250→251)
2026-03-12T16:43:39.860Z [DEBUG] [useDeferredValue] Messages deferred by 1 (250→251)
2026-03-12T16:43:45.861Z [DEBUG] Getting matching hook commands for Notification with query: permission_prompt
2026-03-12T16:43:45.861Z [DEBUG] Found 0 hook matchers in settings
2026-03-12T16:43:45.861Z [DEBUG] Matched 0 unique hooks for query "permission_prompt" (0 before deduplication)
[log ends — process alive but completely frozen, no further debug output]



16 0x16 0x402c542c 0x7ffef19315f0 0x2a015d800011 0x0 0x2 0x7ffef19315f0 0x7ff7c7d19748
(syscall 16 = ioctl, TIOCSWINSZ — terminal resize loop)



[das@l:~/.claude/debug]$ tail -n 50 ~/.claude/debug/latest 
2026-03-12T16:43:39.661Z [DEBUG] Preserving file permissions: 100600
2026-03-12T16:43:39.662Z [DEBUG] Temp file written successfully, size: 62951 bytes
2026-03-12T16:43:39.662Z [DEBUG] Applied original permissions to temp file
2026-03-12T16:43:39.662Z [DEBUG] Renaming /home/das/.claude.json.tmp.3838599.1773333819661 to /home/das/.claude.json
2026-03-12T16:43:39.663Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:39.671Z [DEBUG] Writing to temp file: /home/das/.claude.json.tmp.3838599.1773333819671
2026-03-12T16:43:39.671Z [DEBUG] Preserving file permissions: 100600
2026-03-12T16:43:39.673Z [DEBUG] Temp file written successfully, size: 62951 bytes
2026-03-12T16:43:39.674Z [DEBUG] Applied original permissions to temp file
2026-03-12T16:43:39.674Z [DEBUG] Renaming /home/das/.claude.json.tmp.3838599.1773333819671 to /home/das/.claude.json
2026-03-12T16:43:39.675Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:39.680Z [DEBUG] Writing to temp file: /home/das/.claude.json.tmp.3838599.1773333819680
2026-03-12T16:43:39.680Z [DEBUG] Preserving file permissions: 100600
2026-03-12T16:43:39.681Z [DEBUG] Temp file written successfully, size: 62951 bytes
2026-03-12T16:43:39.681Z [DEBUG] Applied original permissions to temp file
2026-03-12T16:43:39.681Z [DEBUG] Renaming /home/das/.claude.json.tmp.3838599.1773333819680 to /home/das/.claude.json
2026-03-12T16:43:39.682Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:39.693Z [DEBUG] Fast mode unavailable: Fast mode requires extra usage billing · /extra-usage to enable
2026-03-12T16:43:39.702Z [DEBUG] Fast mode unavailable: Fast mode requires extra usage billing · /extra-usage to enable
2026-03-12T16:43:39.705Z [DEBUG] executePreToolHooks called for tool: ExitPlanMode
2026-03-12T16:43:39.706Z [DEBUG] Getting matching hook commands for PreToolUse with query: ExitPlanMode
2026-03-12T16:43:39.706Z [DEBUG] Found 0 hook matchers in settings
2026-03-12T16:43:39.706Z [DEBUG] Matched 0 unique hooks for query "ExitPlanMode" (0 before deduplication)
2026-03-12T16:43:39.706Z [DEBUG] executePermissionRequestHooks called for tool: ExitPlanMode
2026-03-12T16:43:39.707Z [DEBUG] Getting matching hook commands for PermissionRequest with query: ExitPlanMode
2026-03-12T16:43:39.707Z [DEBUG] Found 0 hook matchers in settings
2026-03-12T16:43:39.707Z [DEBUG] Matched 0 unique hooks for query "ExitPlanMode" (0 before deduplication)
2026-03-12T16:43:39.707Z [DEBUG] [useDeferredValue] Messages deferred by 1 (250→251)
2026-03-12T16:43:39.860Z [DEBUG] [useDeferredValue] Messages deferred by 1 (250→251)
2026-03-12T16:43:39.864Z [DEBUG] Writing to temp file: /home/das/.claude.json.tmp.3838599.1773333819864
2026-03-12T16:43:39.864Z [DEBUG] Preserving file permissions: 100600
2026-03-12T16:43:39.865Z [DEBUG] Temp file written successfully, size: 62951 bytes
2026-03-12T16:43:39.865Z [DEBUG] Applied original permissions to temp file
2026-03-12T16:43:39.865Z [DEBUG] Renaming /home/das/.claude.json.tmp.3838599.1773333819864 to /home/das/.claude.json
2026-03-12T16:43:39.866Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:39.974Z [DEBUG] Writing to temp file: /home/das/.claude.json.tmp.3838599.1773333819974
2026-03-12T16:43:39.974Z [DEBUG] Preserving file permissions: 100600
2026-03-12T16:43:39.976Z [DEBUG] Temp file written successfully, size: 62951 bytes
2026-03-12T16:43:39.977Z [DEBUG] Applied original permissions to temp file
2026-03-12T16:43:39.977Z [DEBUG] Renaming /home/das/.claude.json.tmp.3838599.1773333819974 to /home/das/.claude.json
2026-03-12T16:43:39.978Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:40.010Z [DEBUG] Writing to temp file: /home/das/.claude.json.tmp.3838599.1773333820010
2026-03-12T16:43:40.010Z [DEBUG] Preserving file permissions: 100600
2026-03-12T16:43:40.012Z [DEBUG] Temp file written successfully, size: 62951 bytes
2026-03-12T16:43:40.013Z [DEBUG] Applied original permissions to temp file
2026-03-12T16:43:40.013Z [DEBUG] Renaming /home/das/.claude.json.tmp.3838599.1773333820010 to /home/das/.claude.json
2026-03-12T16:43:40.014Z [DEBUG] File /home/das/.claude.json written atomically
2026-03-12T16:43:45.861Z [DEBUG] Getting matching hook commands for Notification with query: permission_prompt
2026-03-12T16:43:45.861Z [DEBUG] Found 0 hook matchers in settings
2026-03-12T16:43:45.861Z [DEBUG] Matched 0 unique hooks for query "permission_prompt" (0 before deduplication)

[das@l:~/.claude/debug]$

Steps to Reproduce

Reproduction

  1. Run a long agentic session (complex tasks, many tool calls, background bash commands)
  2. Let the session reach ~200+ messages
  3. Trigger an approval prompt while background commands are still running/streaming
  4. TUI freezes completely — no input accepted

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.92

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Other

Additional Information

Environment

Claude Code: 2.1.92 (nixpkgs unstable)
OS: NixOS 26.05 (Yarara), kernel 6.19.11
CPU: AMD Ryzen Threadripper PRO 3945WX (24 cores)
Terminal: GNOME Console 49.2 (VTE-based, Wayland/Mutter)
TERM: xterm-256color
Install: nixpkgs claude-code package via home-manager
Displays: 3 monitors including 5120x1440 @ 120Hz

[das@l:~/.claude/debug]$ fastfetch
          ▗▄▄▄       ▗▄▄▄▄    ▄▄▄▖             das@l
          ▜███▙       ▜███▙  ▟███▛             -----
           ▜███▙       ▜███▙▟███▛              OS: NixOS 26.05 (Yarara) x86_64
            ▜███▙       ▜██████▛               Host: 30E1S30400 (ThinkStation P620)
     ▟█████████████████▙ ▜████▛     ▟▙         Kernel: Linux 6.19.11
    ▟███████████████████▙ ▜███▙    ▟██▙        Uptime: 1 day, 16 hours, 16 mins
           ▄▄▄▄▖           ▜███▙  ▟███▛        Packages: 1984 (nix-system), 1386 (nix-user)
          ▟███▛             ▜██▛ ▟███▛         Shell: bash 5.3.9
         ▟███▛               ▜▛ ▟███▛          Display (DELL S2817Q): 3840x2160 in 28", 60 Hz [External]
▟███████████▛                  ▟██████████▙    Display (LS49AG95): 5120x1440 in 49", 120 Hz [External]
▜██████████▛                  ▟███████████▛    Display (DELL S2817Q): 3840x2160 in 28", 60 Hz [External]
      ▟███▛ ▟▙               ▟███▛             DE: GNOME 49.4
     ▟███▛ ▟██▙             ▟███▛              WM: Mutter (Wayland)
    ▟███▛  ▜███▙           ▝▀▀▀▀               WM Theme: Nordic
    ▜██▛    ▜███▙ ▜██████████████████▛         Theme: Nordic [GTK2/3/4]
     ▜▛     ▟████▙ ▜████████████████▛          Icons: Papirus-Dark [GTK2/3/4]
           ▟██████▙         ▜███▙              Font: Adwaita Sans (11pt) [GTK2/3/4]
          ▟███▛▜███▙         ▜███▙             Cursor: Adwaita (24px)
         ▟███▛  ▜███▙         ▜███▙            Terminal: GNOME Console 49.2
         ▝▀▀▀    ▀▀▀▀▘         ▀▀▀▘            Terminal Font: Adwaita Mono (11pt)
                                               CPU: AMD Ryzen Threadripper PRO 3945WXs (24) @ 4.43 GHz
                                               GPU 1: NVIDIA GeForce RTX 3070 [Discrete]
                                               GPU 2: AMD Radeon Pro W7500 [Discrete]
                                               Memory: 30.16 GiB / 125.64 GiB (24%)
                                               Swap: 0 B / 138.21 GiB (0%)
                                               Disk (/): 1.26 TiB / 1.66 TiB (76%) - ext4
                                               Local IP (enp1s0): 172.16.50.219/24
                                               Locale: en_US.UTF-8

                                                                       
                                                                       

[das@l:~/.claude/debug]$ 

View original on GitHub ↗

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