Skip to content

fix(terminal): stop the find bar from crashing a node after a narrowing resize - #1313

Merged
eneskirca merged 2 commits into
eneskirca:mainfrom
ezwep:fix/find-crash-alt-screen
Oct 28, 2026
Merged

eneskirca merged 2 commits into
eneskirca:mainfrom
ezwep:fix/find-crash-alt-screen

Conversation

@ezwep

@ezwep ezwep commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Closes #1312

Typing in the find bar of a Claude Code node that had been made narrower replaced the node with "This node hit an error — This API only accepts positive integers". The cause is in xterm: on a narrowing resize it trims buffer lines only when the buffer reflows, and the alternate buffer never does, so the search addon reads cells past the right edge and computes a negative decoration width. Details are in the issue.

Change

  • New terminal/shrink-trim.ts, patchShrinkTrim(term): on a resize that narrows the terminal, the alternate buffer's lines are trimmed to the new width. That is the same call (BufferLine.resize) xterm makes for a buffer that reflows. The trimmed cells are past the right edge, so they are not on screen; after widening they come back blank, as they do in a reflowing buffer, instead of showing the old text until the app repaints.
  • Called in TerminalNode on a fresh xterm before the first fit (a parked xterm already has it), and in the kanban ModalTerminal before its fit.
  • Guarded and fail-open like patchViewportScrollSync: if the private fields are missing on another xterm version, it leaves stock behavior; a second call is a no-op.
  • Only the alternate buffer. The normal buffer is trimmed by xterm itself when it has scrollback; a test pins that a find there does not throw without the patch. Neither terminal sets scrollback: 0 or windowsPty, the two things that turn reflow off.

Alternative considered

Guarding the search side instead is possible, but skipping the bad decoration alone is not enough: the addon would still count text that is no longer on screen as hits, and its row loop would carry the negative width over into a highlight on the next row. A search-side fix would have to bound hits and row continuation as well, inside the addon. Trimming removes the stale text where it comes from, and also fixes the widening case.

Checks

  • shrink-trim.test.ts, with a real xterm and the real search addon in jsdom: the crash reproduces without the patch; with it a find no longer throws, cut-off text is no longer counted as a hit, a hit still on screen is still found, widening shows blank cells instead of the cut-off text, a wide character cut by the new edge, the normal buffer needs no patch, idempotence and fail-open; plus source pins that both terminals call it.
  • In Electron with xterm 5.5.0 + addon-search 0.16.0 and the captured screen of the pane where it happened: it throws without the patch and not with it.
  • vitest run src/renderer: 9010 passed (run before the wide-character test was added; shrink-trim.test.ts now has 10 tests, all passing). The 5 failures are in sessionRename.realtty.test.ts (posix_spawnp failed) and fail the same way without this change, because node-pty in this checkout is built for Electron. npm run typecheck: clean.

Not checked

  • In a built app by hand.
  • The WebGL renderer and the shared glyph grid with the patch applied (the tests and the Electron check use the DOM renderer).
  • The Windows session host's headless xterm is not changed; it has no find bar.
  • The patch relies on xterm internals (_core.buffers, BufferLine.resize). The fail-open guard only covers missing fields, not changed behavior, so an xterm upgrade should rerun these tests; they use the real xterm, so they would show it.
  • Whether xterm.js wants this fixed upstream. Once a fix is in the xterm version nodeterm ships, this patch can go.

ezwep added 2 commits October 26, 2026 16:51
…ng resize

xterm trims buffer lines on a narrowing resize only for a buffer that
reflows, and the alternate buffer (every Claude Code node) never does.
The search addon then reads the cut-off cells, computes a negative
decoration width for a hit past the right edge, and registerDecoration
throws 'This API only accepts positive integers' inside the find-bar
effect, so the node's error boundary replaces the whole node.

patchShrinkTrim trims the alternate buffer's lines to the new width on
a narrowing resize, the same thing xterm does to a reflowing buffer.
Wired into TerminalNode and the kanban ModalTerminal.
@eneskirca
eneskirca merged commit 28d4bcf into eneskirca:main Oct 28, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Find bar crashes a node with "This API only accepts positive integers" after the node was made narrower

2 participants