Skip to content

fix(ui): prevent status-bar panic on multi-byte error messages - #14

Open
svaiml wants to merge 1 commit into
zombocoder:mainfrom
svaiml:svaiml/ghdhunt/status-bar-utf8-panic
Open

fix(ui): prevent status-bar panic on multi-byte error messages#14
svaiml wants to merge 1 commit into
zombocoder:mainfrom
svaiml:svaiml/ghdhunt/status-bar-utf8-panic

Conversation

@svaiml

@svaiml svaiml commented Jul 27, 2026

Copy link
Copy Markdown

Problem

render_status_bar truncates an overflowing status line with a raw byte slice:

format!("{}...", &status[..center_width.saturating_sub(3)])

When the status line holds an error message, that message can contain multi-byte
UTF-8 characters — GitHub API error bodies, GraphQL error text, and org/repo
names all routinely do. If center_width - 3 falls inside such a character,
the slice panics with byte index N is not a char boundary. Because this runs
inside the ratatui draw closure, the panic tears down the whole TUI and leaves
the terminal in a broken raw state.

The truncation branch triggers whenever status.len() > center_width, i.e. on a
sufficiently narrow terminal (or a long error) — so a single non-ASCII byte in an
error message is enough to crash the app on the next frame.

Fix

Extract the truncation into a small truncate_status helper that walks the cut
point back to the nearest UTF-8 character boundary before appending the ellipsis.
Behaviour is byte-for-byte identical for ASCII status lines; multi-byte lines are
now cut safely instead of panicking.

Tests

Added unit tests for:

  • no truncation when the status fits,
  • ASCII truncation with the ellipsis,
  • a cut that lands inside a multi-byte character (the previous panic),
  • a sweep over every width of a multi-byte-dense string to guarantee the path is
    panic-free.

cargo build --all-targets, cargo test, cargo clippy --all-targets -- -D warnings, and cargo fmt --check all pass.

The status bar truncates an overflowing status line with a byte slice at
`center_width - 3`. When the status holds an error message containing
multi-byte UTF-8 characters (GitHub API error bodies, GraphQL messages,
org/repo names), that index can fall inside a character, so the slice
panics with `byte index N is not a char boundary` and takes down the whole
TUI draw loop, leaving the terminal in a broken raw state.

Extract the truncation into `truncate_status`, which walks the cut point
back to the nearest UTF-8 char boundary before appending the ellipsis.
Behaviour is unchanged for ASCII status lines.

Add unit tests covering the fit/no-truncation case, ASCII truncation, a cut
that lands inside a multi-byte character, and a sweep over every width of a
multi-byte-dense string to guarantee the path is panic-free.

Signed-off-by: svaiml <88979468+svaiml@users.noreply.github.com>
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.

1 participant