Skip to content

fix(tui): drop corrupted SGR mouse garbage that leaked into composer - #34317

Closed
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:fix/tui-sgr-mouse-fragment-leakage
Closed

fix(tui): drop corrupted SGR mouse garbage that leaked into composer#34317
konsisumer wants to merge 1 commit into
NousResearch:mainfrom
konsisumer:fix/tui-sgr-mouse-fragment-leakage

Conversation

@konsisumer

Copy link
Copy Markdown
Contributor

What changed and why

Under heavy render backpressure in tmux/WezTerm, dozens of SGR mouse events accumulate in the tty buffer. The 50 ms flush timer splits ESC from its continuation bytes, so subsequent reads arrive as plain text. parseTextWithSgrMouseFragments already recovers adjacent valid fragments as a burst, but the corrupted/partial bytes surrounding those matches (e.g. 5;34M;34M — fragments with only one semicolon, or two consecutive M terminators) were passed verbatim to parseKeypress, which emitted them as garbage text into the composer.

This PR adds MOUSE_GARBAGE_RE (/^[\d;Mm\[<]+$/) and applies it to any gap or tail text adjacent to a consumed burst: if the slice consists solely of characters that appear in SGR mouse event streams, it is silently discarded. Real trailing text (e.g. user-typed 'hello') is unaffected because it contains non-mouse characters.

The bug was reported by two independent users:

  • Original reporter on Linux/WSL2 + tmux, reproducing with ~271k-token sessions
  • iseppe on WSL2 Ubuntu 24.04 + WezTerm, triggered by double-clicking a link

Both environments confirm the leakage is not tmux-specific but inherent to the fragment-recovery fallback when mouse events arrive faster than the event loop can drain stdin.

How to test

  1. Start hermes --tui inside tmux or WezTerm with mouse tracking enabled (default display.tui_mouse: true or all)
  2. Open a large session (200k+ tokens) to create render backpressure
  3. Move the mouse rapidly across the terminal for several seconds
  4. Verify the composer () stays clean — no digit;digit;digitM garbage
  5. Run the unit tests: cd ui-tui && npm test -- packages/hermes-ink/src/ink/parse-keypress.test.ts
    • 19 tests pass including 4 new regression tests for the garbage-drop behavior

What platforms tested on

  • macOS (unit tests only; the parser fix is platform-agnostic)
  • Reported affected platforms: Linux/WSL2 + tmux, Linux/WSL2 + WezTerm

Fixes #18658

Under heavy render backpressure in tmux/WezTerm, dozens of SGR mouse
events can accumulate in the tty buffer. The 50ms flush timer splits
ESC from its continuation, so subsequent reads arrive as raw text.
parseTextWithSgrMouseFragments recovers adjacent valid fragments as a
burst, but the corrupted/partial bytes before or after those matches
(e.g. '5;34M;34M' — missing a semicolon pair) were passed verbatim to
parseKeypress, which emitted them as garbage text into the composer.

Add MOUSE_GARBAGE_RE (/^[\d;Mm\[<]+$/) and apply it to any gap or tail
text adjacent to a consumed burst: if the slice consists solely of
characters found in SGR mouse event streams, silently discard it rather
than leaking it as visible input. Real trailing text (e.g. 'typed') is
unaffected because it contains non-mouse characters.

Fixes NousResearch#18658
@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists labels May 29, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Part of the SGR mouse sequence leakage chain: #17701#18113#26781#28463#29337. Fixes #18658. Competes with open PRs #26781 and #29337 for the same bug.

@konsisumer

Copy link
Copy Markdown
Contributor Author

Thanks @alt-glitch for the chain context.

I see two open PRs already targeting the same root cause:

This PR uses a MOUSE_GARBAGE_RE whitelist to silently discard gap/tail text composed solely of mouse-alphabet characters adjacent to a matched burst — a different strategy than either of the above, but same root cause and same affected file.

Should I close this PR in favor of one of the existing ones, or is there value in keeping all three open while a canonical fix is chosen? Happy to close and redirect effort to whichever approach you prefer.

@teknium1

teknium1 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Closing as redundant against current main.

This is part of the TUI/CLI ANSI/SGR/escape-leak cluster, most of which is already solved on main:

Your work here overlapped this already-merged coverage. Thanks for the contribution and for helping surface the leak class — it's appreciated.

@teknium1 teknium1 closed this Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(tui): SGR mouse sequence leakage into composer under heavy render in tmux

3 participants