{"record":{"id":"08b6cf4a2dd1c4c6","repo":"jdx/mise","slug":"failed-to-open-the-editor-program-err-set","errorCode":null,"errorMessage":"failed to open the editor `{program}`: {err}\nSet $EDITOR or $VISUAL to an editor mise can run.","messagePattern":"failed to open the editor `(.+?)`: (.+?)\nSet \\$EDITOR or \\$VISUAL to an editor mise can run\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/editor.rs","lineNumber":23,"sourceCode":"/// Open `file` in the user's editor and wait for it to exit.\n///\n/// The wait is part of the contract, not an accident of blocking IO: `mise dot edit --apply`\n/// converges the target as soon as this returns, so an editor that detached would apply a file the\n/// user had not saved yet.\npub(super) fn open_in_editor(file: &Path) -> Result<()> {\n    open_in_editor_with(&crate::env::EDITOR, file)\n}\n\n/// Takes the editor rather than reading it, so the failure path can be driven from a test.\nfn open_in_editor_with(editor: &str, file: &Path) -> Result<()> {\n    let (program, mut args) = split_editor_command(editor)?;\n    args.push(file.as_os_str().into());\n    if let Err(err) = crate::cmd::cmd(&program, args).run() {\n        // Name the program and the variables that choose it. A child that never starts comes back\n        // as std's bare \"program not found\" (see the note in `backend::which_spawnable`), which\n        // says neither what mise tried to run nor where the name came from — and the default is\n        // the name most likely to be missing.\n        bail!(\n            \"failed to open the editor `{program}`: {err}\\n\\\n             Set $EDITOR or $VISUAL to an editor mise can run.\"\n        );\n    }\n    Ok(())\n}\n\nfn split_editor_command(editor: &str) -> Result<(String, Vec<OsString>)> {\n    let mut parts = shell_words::split(editor)\n        .map_err(|e| eyre!(\"failed to parse EDITOR/VISUAL value {:?}: {}\", editor, e))?\n        .into_iter();\n    let program = parts\n        .next()\n        .ok_or_else(|| eyre!(\"EDITOR/VISUAL is empty\"))?;\n\n    Ok((program, parts.map(Into::into).collect()))\n}\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/cli/editor.rs#L5-L41","documentation":"`mise editor` (and commands spawning an editor) failed to launch the chosen editor program. The error names the program and points at $EDITOR/$VISUAL because the default editor name is typically the one missing from PATH.","triggerScenarios":"crate::cmd::cmd(&program, args).run() returns Err — the editor binary does not exist or cannot be exec'd — most often when $EDITOR/$VISUAL is unset and the fallback program (e.g. an editor not installed) cannot start.","commonSituations":"Running mise in a minimal container or CI where no editor is installed; $EDITOR set to a non-existent binary; PATH missing the editor directory.","solutions":["Set $EDITOR or $VISUAL to an installed editor (e.g. export EDITOR=vim or code --wait)","Install the editor the variable names, or fix the PATH so it is found","Verify with `command -v \"$EDITOR\"` that the program resolves"],"exampleFix":"// before\nmise editor        # EDITOR unset, no default editor on PATH\n// after\nexport EDITOR=\"code --wait\"\nmise editor","handlingStrategy":"fallback","validationCode":"command -v \"${EDITOR:-vi}\" >/dev/null || echo 'editor missing'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set EDITOR in shell profile","Verify editor binaries exist in containers/CI images"],"tags":["cli","editor","env"],"backgroundTag":"command-not-found","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}