Skip to content

Fix TUI panic on narrow terminal: negative strings.Repeat count#19

Merged
phiat merged 1 commit into
mainfrom
fix/stream-narrow-terminal-panic
May 6, 2026
Merged

Fix TUI panic on narrow terminal: negative strings.Repeat count#19
phiat merged 1 commit into
mainfrom
fix/stream-narrow-terminal-panic

Conversation

@phiat
Copy link
Copy Markdown
Owner

@phiat phiat commented May 6, 2026

Summary

  • Fixes a panic (strings: negative Repeat count) that crashed the TUI when the terminal was resized so that the stream pane's effective inner width dropped below 4 columns.
  • Adds a regression test exercising every render branch with widths down to -10.

Root cause

StreamView.SetSize clamped innerWidth/innerHeight for the viewport but stored the raw caller-provided width in s.width. With the tree visible, model.go:456 calls SetSize(m.width-m.treeWidth-5, ...), which can go negative on narrow terminals. updateContent then computed contentWidth := s.width - 4 (more negative), passed it to renderItem, where strings.Repeat(\"─\", min(width, 60)) panicked.

Trace from the user's crash:

strings.Repeat({0x5d92cb?, 0x400?}, 0x0?)  → panic
internal/tui.(*StreamView).renderItem  stream.go:342
internal/tui.(*StreamView).updateContent stream.go:206
internal/tui.(*StreamView).SetSize       stream.go:82
internal/tui.(*Model).updateLayout       model.go:456

Fix

  • Clamp contentWidth to a minimum of 1 in updateContent, mirroring the existing innerWidth clamp in SetSize.
  • Defensively guard the strings.Repeat site in renderItem so a negative width can never reach it again.

Audit

I scanned the TUI for the same class of bug:

  • tree.go — three strings.Repeat sites; each already gated by if X < 1 { X = 1 } or if gap >= 1. Safe.
  • stream.go::truncateContent — already guards with width > 0. Safe.
  • model.go::wrappedRows — guards m.width <= 0. Safe.

The only similar-class bug was the one fixed here.

Test plan

  • go build ./...
  • go test ./... passes
  • New TestStreamView_NarrowResizeDoesNotPanic panics on the unfixed code (verified by temporarily reverting) and passes with the fix
  • Manual: resize terminal narrow with tree visible — TUI no longer crashes

Closes claude-esp-5k0.

🤖 Generated with Claude Code

When the terminal is resized so that m.width-m.treeWidth-5 drops below 4,
SetSize stored a small/negative raw width in s.width while clamping only
the viewport's innerWidth. updateContent then computed contentWidth as
s.width-4 (negative), passed it through to renderItem, where
strings.Repeat("─", min(width, 60)) panicked with "negative Repeat
count" and crashed the TUI.

Clamp contentWidth in updateContent to a minimum of 1, mirroring the
existing innerWidth clamp in SetSize, and defensively guard the
strings.Repeat call site so a negative width can never reach it again.

Closes claude-esp-5k0

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@phiat phiat merged commit 3490a28 into main May 6, 2026
2 checks passed
@phiat phiat deleted the fix/stream-narrow-terminal-panic branch May 6, 2026 16:52
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