{"record":{"id":"1432bd23007ced39","repo":"sipeed/picoclaw","slug":"failed-to-parse-editor-w","errorCode":null,"errorMessage":"failed to parse $EDITOR: %w","messagePattern":"failed to parse \\$EDITOR: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/mcp/edit.go","lineNumber":35,"sourceCode":"\t\tShort: \"Open the PicoClaw config in $EDITOR\",\n\t\tArgs:  cobra.NoArgs,\n\t\tRunE: func(cmd *cobra.Command, _ []string) error {\n\t\t\teditor := strings.TrimSpace(os.Getenv(\"EDITOR\"))\n\t\t\tif editor == \"\" {\n\t\t\t\treturn fmt.Errorf(\"$EDITOR is not set\")\n\t\t\t}\n\n\t\t\tcfg, err := loadConfig()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err = saveValidatedConfig(cfg); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\teditorArgs, err := shlex.Split(editor)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to parse $EDITOR: %w\", err)\n\t\t\t}\n\t\t\tif len(editorArgs) == 0 {\n\t\t\t\treturn fmt.Errorf(\"$EDITOR is empty\")\n\t\t\t}\n\n\t\t\teditorArgs = append(editorArgs, internal.GetConfigPath())\n\t\t\tprocess := editorCommand(editorArgs[0], editorArgs[1:]...)\n\t\t\tprocess.Stdin = cmd.InOrStdin()\n\t\t\tprocess.Stdout = cmd.OutOrStdout()\n\t\t\tprocess.Stderr = cmd.ErrOrStderr()\n\n\t\t\tif err := process.Run(); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to start editor: %w\", err)\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/mcp/edit.go#L17-L53","documentation":"The EDITOR value is split with shlex (edit.go:33-36) so multi-word values like `code --wait` work; if the shell-style string is malformed — classically unbalanced quotes — shlex.Split returns an error, wrapped here with %w. The parse happens after the config was validated, so no state is changed.","triggerScenarios":"export EDITOR='vim -c \"set ro' (missing closing quote); a dangling backslash; control characters pasted from another terminal.","commonSituations":"Hand-editing dotfiles and leaving an unclosed quote; copying an EDITOR line whose quoting was written for a different shell; nested quoting over SSH.","solutions":["Fix the quoting in EDITOR, or simplify it to a single word (vim, nano)","Move flags into a wrapper script and set EDITOR to the script path","Verify interactively: run \"$EDITOR\" (with the quotes echoed via printf '%s\\n' \"$EDITOR\") before retrying"],"exampleFix":"# before\nexport EDITOR='code --wait \"unclosed'\n# after\nexport EDITOR='code --wait'","handlingStrategy":"validation","validationCode":"import \"github.com/google/shlex\"\n\nif _, err := shlex.Split(editor); err != nil {\n\treturn fmt.Errorf(\"EDITOR %q is not valid shell syntax: %w\", editor, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep EDITOR simple: one word, or flags without nested quotes","Complex editor invocations go in a wrapper script; EDITOR points at the script","After changing EDITOR, test with a trivial shlex split or by launching it once"],"tags":["cli","editor","shell-parsing","environment"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}