sipeed/picoclaw · error

failed to start editor: %w

Error message

failed to start editor: %w

What it means

edit.go:48-50 wraps process.Run() of the spawned editor. Despite the 'failed to start' wording it covers both spawn failures (binary not found in PATH) and non-zero editor exits, since Run covers both; the underlying exec error is preserved via %w. Stdin/stdout/stderr are wired to the terminal, so interactive editors work normally.

Source

Thrown at cmd/picoclaw/internal/mcp/edit.go:48

				return err
			}

			editorArgs, err := shlex.Split(editor)
			if err != nil {
				return fmt.Errorf("failed to parse $EDITOR: %w", err)
			}
			if len(editorArgs) == 0 {
				return fmt.Errorf("$EDITOR is empty")
			}

			editorArgs = append(editorArgs, internal.GetConfigPath())
			process := editorCommand(editorArgs[0], editorArgs[1:]...)
			process.Stdin = cmd.InOrStdin()
			process.Stdout = cmd.OutOrStdout()
			process.Stderr = cmd.ErrOrStderr()

			if err := process.Run(); err != nil {
				return fmt.Errorf("failed to start editor: %w", err)
			}

			return nil
		},
	}
}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Confirm the first word of EDITOR resolves: command -v ${EDITOR%% *}
  2. Run the editor directly on the config path ("$EDITOR" ~/.config/picoclaw/config.json) to see its own error output
  3. For headless/SSH contexts, switch to a terminal editor (vim/nano) for this invocation: EDITOR=vim picoclaw mcp edit

Example fix

# before
export EDITOR=code   # code not on PATH over ssh
picoclaw mcp edit
# after
command -v code || export EDITOR=vim
picoclaw mcp edit
Defensive patterns

Strategy: try-catch

Validate before calling

editorBin=$(printf '%s' "$EDITOR" | cut -d' ' -f1)
command -v "$editorBin" >/dev/null 2>&1 || { echo "editor $editorBin not found in PATH" >&2; exit 127; }
picoclaw mcp edit

Try / catch

if err := editCmd.Execute(); err != nil {
	if strings.Contains(err.Error(), "failed to start editor") {
		// underlying *exec.Error or *exec.ExitError is wrapped via %w:
		// inspect with errors.As to distinguish not-found vs non-zero exit
		var execErr *exec.ExitError
		if errors.As(err, &execErr) {
			fmt.Fprintf(os.Stderr, "editor exited %s\n", execErr.ExitCode())
		}
	}
}

Prevention

When it happens

Trigger: EDITOR points to a binary not installed or not on PATH in this shell; the editor exits non-zero (vim :cq, crashed plugin); $TERM unset in a headless session makes the editor bail immediately.

Common situations: EDITOR=code over SSH without the VS Code CLI on PATH; tmux/screen without TERM; broken editor config causing instant exit; EDITOR left over from another machine.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/bb2c04028c3331ca. Report an issue: GitHub.