{"record":{"id":"963ee2896268969c","repo":"ipfs/kubo","slug":"env-variable-editor-not-set","errorCode":null,"errorMessage":"ENV variable $EDITOR not set","messagePattern":"ENV variable \\$EDITOR not set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/config.go","lineNumber":609,"sourceCode":"}\n\nfunc setConfig(r repo.Repo, key string, value any) (*ConfigField, error) {\n\terr := r.SetConfigKey(key, value)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to set config value: %s (maybe use --json?)\", err)\n\t}\n\treturn getConfig(r, key)\n}\n\n// parseEditorCommand parses the EDITOR environment variable into command and arguments\nfunc parseEditorCommand(editor string) ([]string, error) {\n\treturn shlex.Split(editor, true)\n}\n\nfunc editConfig(filename string) error {\n\teditor := os.Getenv(\"EDITOR\")\n\tif editor == \"\" {\n\t\treturn errors.New(\"ENV variable $EDITOR not set\")\n\t}\n\n\teditorAndArgs, err := parseEditorCommand(editor)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot parse $EDITOR value: %s\", err)\n\t}\n\teditor = editorAndArgs[0]\n\targs := append(editorAndArgs[1:], filename)\n\n\tcmd := exec.Command(editor, args...)\n\tcmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr\n\treturn cmd.Run()\n}\n\n// nodePeerID derives the PeerID implied by the private key stored in the repo\n// config. Identity.PeerID must equal this value; the node refuses to start\n// when the two disagree.\nfunc nodePeerID(r repo.Repo) (peer.ID, error) {","sourceCodeStart":591,"sourceCodeEnd":627,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/config.go#L591-L627","documentation":"`ipfs config edit` opens the config file in the editor named by $EDITOR. Kubo throws this when the EDITOR environment variable is empty or unset, because it refuses to guess which editor to launch. The command exits without modifying the config.","triggerScenarios":"Running `ipfs config edit` in an environment where EDITOR is not exported: bare docker containers, CI jobs, cron/systemd services, fresh shells, or SSH sessions without a login rc file.","commonSituations":"Using ipfs inside a minimal Docker image or container where no editor env var is set; running the command from a daemonized/scripted context that has no interactive environment.","solutions":["Set EDITOR before running: `EDITOR=vim ipfs config edit` (or nano/emacs/vi)","Export it persistently: `echo 'export EDITOR=vim' >> ~/.bashrc && source ~/.bashrc`","Skip the editor entirely: use `ipfs config <key> <value>` or `ipfs config replace <file>` instead","Also consider VISUAL: some setups read VISUAL first; export both to be safe"],"exampleFix":"// before\nipfs config edit\n// after\nEDITOR=nano ipfs config edit","handlingStrategy":"fallback","validationCode":"[ -n \"$EDITOR\" ] || [ -n \"$VISUAL\" ] && echo \"editor set\" || echo \"EDITOR not set: run e.g. EDITOR=vim ipfs config edit\"","typeGuard":null,"tryCatchPattern":"if err := editConfig(tmpfile); err != nil {\n    if strings.Contains(err.Error(), \"$EDITOR not set\") {\n        // fall back to printing the path for manual editing\n        fmt.Println(\"edit manually:\", tmpfile)\n        return nil\n    }\n    return err\n}","preventionTips":["Export EDITOR (and VISUAL) in shell rc files so it survives SSH and scripts","In Docker/CI, pass -e EDITOR=vim to the container or avoid `config edit` entirely","Prefer `ipfs config <key> <value>` / `config replace` in non-interactive contexts","Test `echo $EDITOR` if `ipfs config edit` fails in a new shell"],"tags":["config","environment","editor"],"backgroundTag":"missing-env-var","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}