charmbracelet/bubbletea · warning · ErrProgramKilled
program was killed
Error message
program was killed
What it means
ErrProgramKilled is a sentinel returned by Program.Run when the program was terminated abnormally rather than quitting gracefully: someone called Program.Kill(), the context passed to RunContext/WithContext was cancelled, or the internal event loop failed. It signals that shutdown skipped the final render and terminal restoration ran in 'kill' mode. It is frequently wrapped together with the underlying cause (a context error or the error that killed the loop).
Source
Thrown at tea.go:42
"strconv"
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
"github.com/charmbracelet/colorprofile"
uv "github.com/charmbracelet/ultraviolet"
"github.com/charmbracelet/x/ansi"
"github.com/charmbracelet/x/term"
"github.com/muesli/cancelreader"
)
// ErrProgramPanic is returned by [Program.Run] when the program recovers from a panic.
var ErrProgramPanic = errors.New("program experienced a panic")
// ErrProgramKilled is returned by [Program.Run] when the program gets killed.
var ErrProgramKilled = errors.New("program was killed")
// ErrInterrupted is returned by [Program.Run] when the program get a SIGINT
// signal, or when it receives a [InterruptMsg].
var ErrInterrupted = errors.New("program was interrupted")
// Msg contain data from the result of a IO operation. Msgs trigger the update
// function and, henceforth, the UI.
type Msg = uv.Event
// Model contains the program's state as well as its core functions.
type Model interface {
// Init is the first function that will be called. It returns an optional
// initial command. To not perform an initial command return nil.
Init() Cmd
// Update is called when a message is received. Use it to inspect messages
// and, in response, update the model and/or send a command.
Update(Msg) (Model, Cmd)View on GitHub (pinned to 351d2159f8)
Solutions
- If you intended a clean exit, use p.Quit() or tea.Quit cmd instead of p.Kill()/context cancel
- If cancellation is expected, treat errors.Is(err, tea.ErrProgramKilled) as a normal shutdown path, not a failure
- If it wraps a real cause, unwrap with errors.Unwrap / errors.Is to find the underlying error and fix that (often an input/renderer failure)
- Ensure you are not cancelling the parent context while Run is still expected to render its final frame
Example fix
// before
p := tea.NewProgram(m)
go func() { time.AfterFunc(time.Second, func() { p.Kill() }) }()
// after
p := tea.NewProgram(m)
go func() { time.AfterFunc(time.Second, func() { p.Quit() }) }() Defensive patterns
Strategy: try-catch
Validate before calling
// Decide the shutdown channel before running: // graceful -> p.Quit(); forced -> p.Kill()/ctx cancel (yields ErrProgramKilled)
Type guard
func isProgramKilled(err error) bool {
return err != nil && errors.Is(err, tea.ErrProgramKilled)
} Try / catch
_, err := p.Run()
if isProgramKilled(err) {
// unwrap cause if present
cause := errors.Unwrap(err)
_ = cause
// treat as abnormal-but-expected shutdown
return nil
} Prevention
- Prefer p.Quit() / tea.Quit for normal exits; reserve Kill for hangs
- Scope the context you pass via tea.WithContext to the program's real lifetime
- Document for your users which exit paths return ErrProgramKilled
- Don't spawn goroutines that cancel the context on unrelated errors
When it happens
Trigger: Calling p.Kill() from another goroutine; cancelling the context given to tea.NewProgram(...).RunContext or tea.WithContext; the eventLoop returning a non-nil error (input read failure, renderer failure); a recovered panic (wrapped as ErrProgramKilled: ErrProgramPanic).
Common situations: Embedding a Bubble Tea program in a server where a supervisor cancels the ctx on shutdown; test harnesses that time out and cancel; calling Kill instead of Quit to stop a stuck program; SSH sessions (Wish) dropping and cancelling per-connection contexts.
Related errors
- program experienced a panic
- program was interrupted
- bubbletea: error closing screen writer: %w
- bubbletea: error writing to screen: %w
- bubbletea: error restoring console: %w
AI-assisted analysis of charmbracelet/bubbletea@351d2159f8 (2026-08-15).
Data as JSON: /api/errors/125358651cfd3c8f.
Report an issue: GitHub.