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, err

View on GitHub (pinned to bd4efa277b)

Solutions

  1. 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
  2. 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
  3. 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

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


AI-assisted analysis of junegunn/fzf@bd4efa277b (2026-08-15). Data as JSON: /api/errors/c66a705e4d738a5c. Report an issue: GitHub.