junegunn/fzf · error
invalid become command
Error message
invalid become command
What it means
The proxied command (the fzf invocation inside a shell wrapper, run via RunPrompt in proxy mode) exited with the special ExitBecome code, meaning it asked fzf to 'become' another process, but the file it uses to pass that command was empty. fzf pre-creates the become file with O_EXCL and the child process is supposed to write the NUL-separated command into it; zero bytes means the protocol was violated.
Source
Thrown at src/proxy.go:244
intChan := make(chan os.Signal, 1)
defer close(intChan)
go func() {
if sig, valid := <-intChan; valid {
cmd.Process.Signal(sig)
}
}()
signal.Notify(intChan, os.Interrupt)
if err := cmd.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
code := exitError.ExitCode()
if code == ExitBecome {
data, err := os.ReadFile(becomeFile)
os.Remove(becomeFile)
if err != nil {
return ExitError, err
}
if len(data) == 0 {
return ExitError, errors.New("invalid become command")
}
elems := strings.Split(string(data), "\x00")
command := elems[0]
env := []string{}
if len(elems) > 1 {
env = elems[1:]
}
executor := util.NewExecutor(opts.WithShell)
ttyin, err := tui.TtyIn(opts.TtyDefault)
if err != nil {
return ExitError, err
}
os.Remove(temp)
os.Remove(input)
os.Remove(output)
executor.Become(ttyin, env, command)
}
return code, errView on GitHub (pinned to bd4efa277b)
Solutions
- If you maintain the wrapper: after triggering become, always write the command string (NUL-separated argv) into the become file before exiting with the become code
- If you are a plain user hitting this with stock fzf, report it upstream with the exact keybind/action config — it indicates a corrupted become handshake
- As a workaround, replace --become with execute(...) plus shell-level exec in your keybind
Example fix
# before (broken wrapper) exit 130 # ExitBecome code but nothing written to become file # after printf '%s\0' "$cmd" > "$become_file" exit 130
Defensive patterns
Strategy: try-catch
Try / catch
# in Go, treat this as a fatal protocol error from RunPrompt
code, err := fzf.RunPrompt(...)
if err != nil && strings.Contains(err.Error(), "invalid become command") {
// child violated the become handshake; do not retry, surface it
log.Fatalf("become handshake failed: %v", err)
} Prevention
- Always write the NUL-separated command to the become file before exiting with the become code
- Use stock fzf binaries for become flows; the protocol is internal and version-specific
When it happens
Trigger: Executing the become(...) action (or --become) inside a proxied/prompt context where the child writes nothing to the pre-created become file — e.g. a custom build or script emitting the ExitBecome exit code without the payload, or the write being interrupted.
Common situations: Custom fzf wrappers or plugins that mimic the become protocol incorrectly; a killed/timed-out child that exits with the magic code 130-ish ExitBecome by coincidence; extremely rare in stock usage.
Related errors
- permission denied: ${path}
- invalid history file: ${e.Error()}
- invalid popup option: ${arg} (expected: [center|top|bottom|l
- not a valid integer: ${str}
- not a valid number: ${str}
AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15).
Data as JSON: /api/errors/c66a705e4d738a5c.
Report an issue: GitHub.