junegunn/fzf · error
not a valid number: ${str}
Error message
not a valid number: ${str} What it means
Returned by LightRenderer.getBytesInternal (src/tui/light.go:387) when the input read loop accumulates more than maxInputBuffer (1 MiB, src/tui/light.go:28) bytes without an idle gap. The renderer reads terminal bytes in a tight non-blocking loop (assembling escape sequences and bracketed paste); the overflow check fires only when bytes keep arriving back-to-back, so fzf terminates immediately rather than allocating unbounded memory. The error is fatal: the renderer is closed and a Fatal event propagates.
Source
Thrown at src/options.go:835
}
func isDir(path string) bool {
stat, err := os.Stat(path)
return err == nil && stat.IsDir()
}
func atoi(str string) (int, error) {
num, err := strconv.Atoi(str)
if err != nil {
return 0, errors.New("not a valid integer: " + str)
}
return num, nil
}
func atof(str string) (float64, error) {
num, err := strconv.ParseFloat(str, 64)
if err != nil {
return 0, errors.New("not a valid number: " + str)
}
return num, nil
}
func splitNth(str string) ([]Range, error) {
if match, _ := regexp.MatchString("^[0-9,-.]+$", str); !match {
return nil, errors.New("invalid format: " + str)
}
tokens := strings.Split(str, ",")
ranges := make([]Range, len(tokens))
for idx, s := range tokens {
r, ok := ParseRange(&s)
if !ok {
return nil, errors.New("invalid format: " + str)
}
ranges[idx] = r
}View on GitHub (pinned to bd4efa277b)
Solutions
- Feed large data to fzf on stdin (the candidate list) instead of pasting it into the query line: `huge_file | fzf` or `fzf < query.txt`.
- Find and stop the process flooding the tty: check for runaway writers to the terminal (`ps aux | grep -E 'cat|echo'`, multiplexer panes) and re-run fzf in a clean terminal.
- Keep pastes under ~1 MiB or disable bracketed paste in your terminal emulator if it wraps giant pastes into one uninterrupted escape sequence.
- If you drive fzf programmatically via its tty, write input in chunks with small pauses (>= escPollInterval-scale gaps) so the read loop can flush the buffer between bursts.
- If a specific large paste legitimately must be searched, put it in a file and use fzf's file input rather than the interactive query.
Example fix
# before (pasting a 2 MB block into the query line -> fatal overflow) # fzf <paste of huge.txt> # after (data on stdin, query stays tiny) cat huge.txt | fzf # or preload the initial query from a file within size limits: cat huge.txt | fzf --query="$(head -c 1000 query.txt)"
Defensive patterns
Strategy: validation
Validate before calling
// Shell wrapper: gate pastes/programmatic query injection by size
max_query=100000 # well under fzf's 1 MiB input buffer
if [ "$(wc -c < query.txt)" -gt "$max_query" ]; then
echo "query too large for tty input; use stdin instead" >&2
exit 1
fi
cat items.txt | fzf --query="$(cat query.txt)"
# Go driver writing to fzf's tty: chunk with gaps so fzf's read loop flushes
func writeChunked(w io.Writer, data []byte) error {
for len(data) > 0 {
n := len(data)
if n > 64*1024 {
n = 64 * 1024
}
if _, err := w.Write(data[:n]); err != nil {
return err
}
data = data[n:]
time.Sleep(5 * time.Millisecond) // idle gap lets fzf finish one buffer
}
return nil
} Type guard
func isInputBufferOverflow(stderr string) bool {
return strings.Contains(stderr, "input buffer overflow")
} Try / catch
// fzf exits fatally on this error; the only 'catch' is at the process level:
out, err := cmd.CombinedOutput()
if err != nil && strings.Contains(string(out), "input buffer overflow") {
// relaunch with the large payload delivered via stdin instead of the tty
} Prevention
- Never paste data into fzf's query line; candidate data belongs on stdin.
- Cap programmatic tty writes to fzf and chunk them with small pauses.
- Keep terminal emulators' unlimited-paste of huge clipboards disabled or trimmed.
- Investigate runaway tty writers (cat/echo loops, multiplexer floods) when fzf dies with this error.
When it happens
Trigger: A single burst of uninterrupted terminal input exceeding 1 MiB: pasting (or having a tool write) an extremely large block into the fzf TTY, especially with bracketed-paste escape wrappers; a misbehaving program or script (`cat hugefile > $(tty)`, a runaway loop writing to the terminal, a tmux/screen pane flooding output) feeding continuous bytes so the loop never sees an idle poll; terminal emulators replaying huge scrollback or macros. Normal typing and ordinary pastes never reach 1 MiB in one gapless burst.
Common situations: Pasting an entire minified JS bundle or a huge JSON file into fzf's query line instead of feeding it on stdin; shell scripts that `echo`/`printf` megabytes into the tty where fzf is running; a key-repeating macro or stuck key bridged by a terminal multiplexer; CI harnesses driving fzf's tty with oversized synthetic input; latency spikes on slow links that batch >1 MiB of input into one readable chunk.
Related errors
- invalid border style (expected: rounded|sharp|bold|block|thi
- failed to read %s
- permission denied: ${path}
- invalid history file: ${e.Error()}
- invalid popup option: ${arg} (expected: [center|top|bottom|l
AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15).
Data as JSON: /api/errors/c83ffdbd81ee3843.
Report an issue: GitHub.