Skip to content

Buffer.Resize truncates/drops cells with no reflow, permanently losing content on shrink+grow #180

Description

@muhamm-ad

ultraviolet.Buffer.Resize (buffer.go) truncates/drops cells on shrink with no reflow and nothing preserved:

func (b *Buffer) Resize(width int, height int) {
    ...
    } else if width < curWidth {
        for i := range b.Lines {
            b.Lines[i] = b.Lines[i][:width] // cells beyond width: gone
        }
    }
    ...
    } else if height < len(b.Lines) {
        b.Lines = b.Lines[:height] // rows beyond height: gone
    }
}

Consequences downstream in charmbracelet/x/vt's Emulator.Resize (which calls straight into this for both the main and alt screens):

  • Shrinking width truncates every row to the new width; the trailing cells are discarded, not wrapped onto a new row and not pushed to scrollback.
  • Shrinking height keeps rows [0, newHeight) and drops [newHeight, oldHeight), i.e. it drops the bottom rows, not the top ones a terminal would normally scroll into history.
  • Growing back afterwards only appends blank cells / blank rows, there's nothing left to restore from, so previously-visible content never comes back even though there's room for it again.

Repro

Using vt.NewEmulator directly (no PTY needed):

term := vt.NewEmulator(10, 1)
term.WriteString("0123456789")
term.Resize(5, 1)   // "56789" is now gone
term.Resize(10, 1)  // still gone, row is "01234     "

Expected

At minimum, don't silently discard already-rendered content, e.g. push truncated/dropped cells to the emulator's scrollback (same as Screen.ClearWithScrollback already does on erase) so it's recoverable via scrollback even if live reflow is out of scope. Ideally, real reflow: recompute line wrapping from a logical-line model in both directions, the way terminals like Windows Terminal/iTerm2/kitty do.

Where I hit this

Building an SSH-in-a-TUI pane on top of x/vt (https://github.com/muhamm-ad/bubble-ssh), resizing the pane (e.g. resizing the host terminal window) permanently loses on-screen content that falls outside the new size, and growing back doesn't recover it.

Versions

  • github.com/charmbracelet/ultraviolet, confirmed present in v0.0.0-20260703014108-f5a850f9c2b7 and still present in the latest available commit as of 2026-09-07, v0.0.0-20260906173415-0277a179edd9.
  • github.com/charmbracelet/x/vt, same, v0.0.0-20260730164118-7e2d3e6c5238 through v0.0.0-20260906004030-3986e9119cf9.

Activity

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