Skip to content

truncateMiddle/truncateLeft return longer strings than their budget in narrow terminals #41054

Closed as not planned

Description

@Mute-404

truncateLeft and truncateMiddle in packages/tui/src/util/locale.ts compute a slice length that hits zero or goes negative on small budgets. String.prototype.slice(-0) returns the whole string, so both helpers can return something longer than what they were given:

truncateMiddle("abcdefghij", -1) -> "abcdefghi…bcdefghij"   (19 chars from a 10 char input)
truncateMiddle("abcdefghij",  0) -> "…bcdefghij"
truncateMiddle("abcdefghij",  1) -> "…abcdefghij"
truncateLeft("abcdefghij",   1)  -> "…abcdefghij"

This hits real call sites in narrow terminals. Running the actual expressions from the TUI against the real module:

term | callsite                     | budget | out.len
  10 | dialog-select.tsx:702        |      1 |      40   <- OVERFLOW
  12 | dialog-move-session.tsx:151  |      1 |      40   <- OVERFLOW
  14 | dialog-select.tsx:702        |      2 |      41   <- OVERFLOW
  16 | dialog-move-session.tsx:151  |      2 |      41   <- OVERFLOW

The Math.max(1, ...) at those call sites looks like a guard but clamps right into the broken range. files.tsx:35 uses Math.max(2, ...), which happens to land just outside it.

So the truncate helpers grow the string exactly when the terminal has the least room, and the layout blows out instead of being protected.

Clamping inside the helpers fixes all call sites at once. util/locale.ts currently has no tests. Happy to send a PR with both.

Activity

  1. github-actions commented on Aug 7, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

  2. Mute-404 commented on Aug 7, 2026

    @Mute-404
    Author

    Duplicate of #37458 (and #20880 / #34395 before it). Should have searched before opening this. Closing in favour of the existing issue; my PR #41060 now targets #37458.

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

Metadata

Metadata

Assignees

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