Skip to content

Terminal display corruption: rendered output overlaps/duplicates mid-session #38

Open

Description

@AThraen

Symptom

The terminal display occasionally gets visibly corrupted — chunks of previously-rendered output overlap with current output. The bottom toolbar/status-bar area can appear duplicated, and lines from different parts of the buffer collide on the same row. Screenshot shows it happening inside a Claude session (ink TUI in auto-mode, mid-stream).

(Screenshot will be attached by the reporter — local copy at image-cache/18bf3a04-cb45-439b-ab12-be721bbe0ad9/1.png.)

Likely causes (in order of likelihood)

  1. Resize during in-flight TUI redraw. Ink redraws by ANSI cursor positioning, not full-screen clear. If the WebView2 reports a new size while ink is mid-frame, the next frame writes to addresses that no longer match the visual grid → overlap.
  2. PTY size drift. xterm.js's reported cols/rows and the PTY's ResizePseudoConsole value briefly disagree (e.g. resize message races with output). The shell renders at one size while xterm renders at another.
  3. xterm.js alternate-screen-buffer transition. Switching in/out of the alt buffer (\e[?1049h/l) mid-stream can leave stale rows visible if the transition lands between two write chunks.
  4. Partial-recovery from a stall. May correlate with the intermittent typing-freeze report — if the PTY read loop or WPF dispatcher stalls and then catches up, a backlog of small output chunks could replay out of phase with the app's cursor model.

Repro signals to collect

Not reliably reproducible. When it happens, useful to note:

  • Whether the WPF window or pane was resized in the last few seconds
  • Whether the Claude/TUI session was streaming a long response when corruption appeared
  • Whether enabling Settings > Diagnostics > Trace terminal input/output (PR feat: terminal trace setting + shutdown/restore stability fixes #36) preceding the event captures unusual [DEBUG-tt] gaps in crash.log

Workarounds

  • Resize the pane — typically triggers an app-side redraw and clears the corruption
  • Scroll to the top of the buffer and back
  • Worst case: close and reopen the session

Related

Activity

  1. AThraen commented on Sep 6, 2026

    @AThraen
    ContributorAuthor

    Related: #116 is the initial-render sibling of this, and it disproves two theories

    Filing a cross-link, because the two look alike and shouldn't be merged.

    Same workaround, different trigger, so they're being tracked separately.

    What #116 has established that's relevant here: at startup, xterm and the PTY demonstrably disagree about the column count, and a resize is what reconciles them. That's cause 2 on this issue's likely-causes list ("PTY size drift"), confirmed for at least one code path — which raises its prior for the mid-session case too.

    Two theories are dead and shouldn't be re-tried on either issue:

    1. Font metrics. fix(terminal): re-fit once the font has loaded, not on a timing guess #113 added a re-fit on document.fonts.ready, on the theory that xterm measured the fallback font's advance width before Cascadia Code loaded. It was a no-op — document.fonts.ready resolves once at page load and stays resolved, so the callback ran immediately with identical metrics. fix: release-review findings, verified over three passes #115 replaced it with requestAnimationFrame.
    2. document.fonts.load(). Also a no-op: it matches only CSS-connected FontFace objects, i.e. @font-face rules. There are none — the fonts in play are OS-installed — so it resolves having matched nothing.

    The instrumentation proposed on #116 would serve both: log cols/rows on every fit() and term.onResize page-side, and log what TerminalBridge sets the PTY to. If this issue is size drift, the same trace catches it — with the added question of whether a resize message races an output chunk mid-stream.

    One further datum for cause 4 ("partial recovery from a stall"): the restore loop is now known to stall for seconds at a time under load — measured while investigating #82, where a flat Task.Delay(2000) logged gate=36339ms. If corruption correlates with heavy multi-session activity, that's a real stall to hang the theory on rather than a hypothetical one.

  2. AThraen commented on Sep 9, 2026

    @AThraen
    ContributorAuthor

    This was generated by AI during triage.

    Related: #134 — same underlying class of fault (PTY width disagreeing with xterm's rendered width, ink writing to addresses that don't match the visual grid), but at startup rather than mid-session, and with a traced cause: panes attached to the grid without a re-fit outside the Single layout branch, plus term.onResize suppressing a size report when the recomputed cols is unchanged.

    Cause #2 in this issue's list ("PTY size drift — xterm's reported cols/rows and the PTY's value briefly disagree") is exactly what #134 documents, so a fix there may narrow what's left to explain here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions