[BUG] TUI completely freezes input at high message counts (250+) — ioctl TIOCSWINSZ loop starves event loop on Linux/NixOS
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:
- It defers messages faster than it can process them (useDeferredValue count climbs unbounded)
- The terminal renderer does constant full-screen rewrites (ioctl TIOCSWINSZ loop)
- These together starve the Node.js event loop of cycles needed to process keyboard input
- ~/.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
- Run a long agentic session (complex tasks, many tool calls, background bash commands)
- Let the session reach ~200+ messages
- Trigger an approval prompt while background commands are still running/streaming
- 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]$ This issue has 8 comments on GitHub. Read the full discussion on GitHub ↗