charmbracelet / charmbracelet/bubbles

viewport: panic with slice bounds out of range when height is negative or zero

Open
#879 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
8.9k
Forks
457
Avg merge
1d 18h
Merged PRs (30d)
5

Description

## Description

The viewport panics with `slice bounds out of range` when the `Height` is set to a negative or zero value. This commonly occurs when resizing the terminal window to be very small while using a viewport alongside other components (e.g., textarea).

## Stack Trace

```
runtime error: slice bounds out of range [8:4]

goroutine 1 [running]:
github.com/charmbracelet/bubbles/viewport.Model.visibleLines(...)
viewport/viewport.go:150
github.com/charmbracelet/bubbles/viewport.(*Model).GotoBottom(...)
viewport/viewport.go:348
```

## Root Cause

In `visibleLines()` (viewport.go:143-150), when `Height` becomes negative:

```go
func (m Model) visibleLines() (lines []string) {
h := m.Height - m.Style.GetVerticalFrameSize() // h can be negative
// ...
if len(m.lines) > 0 {
top := max(0, m.YOffset)
bottom := clamp(m.YOffset+h, top, len(m.lines)) // bottom can be < top
lines = m.lines[top:bottom] // PANIC: invalid slice bounds
}
}
```

When `h` is negative and `YOffset` is positive (from a previous scroll), `bottom` becomes less than `top`, causing the panic.

## Steps to Reproduce

1. Create a viewport with another component that takes up vertical space
2. Calculate viewport height as: `msg.Height - otherComponent.Height() - gap`
3. Shrink the terminal window until the calculated height becomes negative
4. The viewport panics

### Minimal Example

```go
case tea.WindowSizeMsg:
m.viewport.Height = msg.Height - m.textarea.Height() - 2 // Can go negative
m.viewport.GotoBottom() // Triggers panic
```

## Suggested Fix

Add a guard in `visibleLines()` to handle the case where `top >= bottom`:

```go
if len(m.lines) > 0 {
top := max(0, m.YOffset)
bottom := clamp(m.YOffset+h, top, len(m.lines))
if top >= bottom {
return nil
}
lines = m.lines[top:bottom]
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.