jdx/mise · error
Git difftool failed ( )
Error message
Git difftool failed ({status}) What it means
The conflicts command shells out to `git difftool` to show local-vs-remote sides of a conflict. Git difftool may exit 1 when the sides differ (treated as success), but any other exit code or signal causes a bail with the exit status.
Solutions
- Check the configured difftool (`git config diff.tool`, `difftool.<tool>.cmd`) and fix or switch to a working tool (e.g. `git config diff.tool vimdiff`)
- Run the difftool manually on the two file paths from the error context to see its real error
- Ensure the difftool exists on PATH and works headless (set a CLI-based tool in SSH/CI environments)
- Re-run `mise dot conflicts` after fixing the difftool config
Example fix
// before $ git config diff.tool kaleidoscope # GUI tool, not installed $ mise dot conflicts error: Git difftool failed (exit status: 127) // after $ git config --global diff.tool vimdiff $ mise dot conflicts
Defensive patterns
Strategy: try-catch
Validate before calling
git difftool --tool-help >/dev/null 2>&1 && echo "difftool configured" || echo "configure diff.tool"
Try / catch
match result {
Err(e) if e.to_string().contains("Git difftool failed") => {
// fix git diff.tool config or PATH, then retry
}
...
} Prevention
- Configure a CLI-friendly difftool (vimdiff, delta) for headless environments
- Test `git difftool` manually before relying on `mise dot conflicts` in scripts
When it happens
Trigger: `git difftool` exits with a code other than 0 or 1 while `mise dot conflicts` renders a conflict diff — usually a misconfigured diff tool or difftool erroring on the given files.
Common situations: `diff.tool` configured to a GUI tool unavailable headless; difftool command not found; difftool crashed on binary/huge files; custom difftool exits with a nonstandard code.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- cannot determine dotfile Git ancestry
- cannot merge dotfile Git history
- checkpoint has no protective checkpoint to undo from
- comparing checkpoints requires git
- dotfile enrollment metadata is too large
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/a0bafaedbc08d579.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/dotfiles/conflicts.rs:144
let local = side_file(repo, conflict.local.as_ref(), path, "local")?;
let remote = side_file(repo, conflict.remote.as_ref(), path, "remote")?;
let git = crate::git::plumbing_binary().ok_or_else(|| eyre::eyre!("git is unavailable"))?;
let mut command = Command::new(git);
crate::git::sanitize_git_command(&mut command);
command
.current_dir(repo.dir().parent().unwrap_or(repo.dir()))
.args(["difftool", "--no-prompt"]);
if let Some(tool) = tool {
command.arg("--tool").arg(tool);
}
command.arg("--no-index").arg("--");
command.arg(local.file.path()).arg(remote.file.path());
let status = command
.status()
.wrap_err_with(|| format!("running Git conflict difftool for {}", display_path(path)))?;
// Like `git diff --no-index`, difftool exits 1 when the sides differ.
if !matches!(status.code(), Some(0 | 1)) {
bail!("Git difftool failed ({status})");
}
if local.mode != remote.mode {
miseprintln!("mode: {} -> {}", local.mode, remote.mode);
}
Ok(())
}
struct SideFile {
file: tempfile::NamedTempFile,
mode: String,
label: String,
}
fn side_file(
repo: &HistoryRepo,
object: Option<&Object>,
path: &Path,
side: &str,View on GitHub (pinned to 533346cc37)