jdx/mise · error
failed to open the editor
Error message
failed to open the editor `{program}`: {err}
Set $EDITOR or $VISUAL to an editor mise can run. What it means
`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.
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
Example fix
// before mise editor # EDITOR unset, no default editor on PATH // after export EDITOR="code --wait" mise editor
Defensive patterns
Strategy: fallback
Validate before calling
command -v "${EDITOR:-vi}" >/dev/null || echo 'editor missing' Prevention
- Always set EDITOR in shell profile
- Verify editor binaries exist in containers/CI images
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Environment variable
- has no value
- --stdin reads the value from stdin; do not provide a value…
- --stdin requires exactly one environment variable key
- a branch name is required
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/08b6cf4a2dd1c4c6.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/editor.rs:23
/// Open `file` in the user's editor and wait for it to exit.
///
/// The wait is part of the contract, not an accident of blocking IO: `mise dot edit --apply`
/// converges the target as soon as this returns, so an editor that detached would apply a file the
/// user had not saved yet.
pub(super) fn open_in_editor(file: &Path) -> Result<()> {
open_in_editor_with(&crate::env::EDITOR, file)
}
/// Takes the editor rather than reading it, so the failure path can be driven from a test.
fn open_in_editor_with(editor: &str, file: &Path) -> Result<()> {
let (program, mut args) = split_editor_command(editor)?;
args.push(file.as_os_str().into());
if let Err(err) = crate::cmd::cmd(&program, args).run() {
// Name the program and the variables that choose it. A child that never starts comes back
// as std's bare "program not found" (see the note in `backend::which_spawnable`), which
// says neither what mise tried to run nor where the name came from — and the default is
// the name most likely to be missing.
bail!(
"failed to open the editor `{program}`: {err}\n\
Set $EDITOR or $VISUAL to an editor mise can run."
);
}
Ok(())
}
fn split_editor_command(editor: &str) -> Result<(String, Vec<OsString>)> {
let mut parts = shell_words::split(editor)
.map_err(|e| eyre!("failed to parse EDITOR/VISUAL value {:?}: {}", editor, e))?
.into_iter();
let program = parts
.next()
.ok_or_else(|| eyre!("EDITOR/VISUAL is empty"))?;
Ok((program, parts.map(Into::into).collect()))
}
View on GitHub (pinned to 533346cc37)