Hmbown/CodeWhale · error · std::io::Error
git not found on PATH
Error message
git not found on PATH
What it means
NotFound error raised when crate::dependencies::Git::command() cannot resolve the git executable on PATH and the snapshot repo then needs to run commit-tree (commit_tree_preserving_date, used during history rebuild/prune to keep survivor commits' original dates). Every snapshot git invocation goes through this dependency shim, so a missing git binary disables snapshots entirely.
Source
Thrown at crates/tui/src/snapshot/repo.rs:794
&["update-ref", "HEAD", &final_sha],
)?;
if !up.status.success() {
return Err(io_other(format!(
"update-ref HEAD failed: {}",
String::from_utf8_lossy(&up.stderr).trim()
)));
}
}
Ok(())
}
/// Run a `commit-tree` invocation with the author/committer dates pinned
/// to `timestamp` (Unix seconds), so a rebuilt survivor keeps its real
/// age instead of stamping "now".
fn commit_tree_preserving_date(&self, args: &[&str], timestamp: i64) -> io::Result<String> {
let date = format!("{timestamp} +0000");
let out = crate::dependencies::Git::command()
.ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "git not found on PATH"))?
.arg("--git-dir")
.arg(&self.git_dir)
.arg("--work-tree")
.arg(&self.work_tree)
.env("GIT_AUTHOR_DATE", &date)
.env("GIT_COMMITTER_DATE", &date)
.args(args)
.output()?;
if !out.status.success() {
return Err(io_other(format!(
"commit-tree failed: {}",
String::from_utf8_lossy(&out.stderr).trim()
)));
}
Ok(String::from_utf8_lossy(&out.stdout).trim().to_string())
}
/// Keep only the latest `max_count` snapshots, dropping older ones.View on GitHub (pinned to 0c42157ee5)
Solutions
- Install git and confirm `git --version` works in the same environment the app runs in
- If launching from a GUI, start the app from a login shell or configure the launcher to inherit a PATH that includes git (/usr/bin, /opt/homebrew/bin, ~/.nix-profile/bin)
- In containers/images, add git to the image rather than relying on runtime mounting
Example fix
# before $ open -a Codewhale # PATH=/usr/bin:/bin:/usr/sbin:/sbin -> Err: git not found on PATH # after $ /opt/homebrew/bin/git --version # verify location $ codewhale # launched from login shell with git on PATH
Defensive patterns
Strategy: validation
Validate before calling
// Verify git is resolvable in the app's own environment before enabling snapshots.
if which::which("git").is_err() {
eprintln!("snapshots require git on PATH");
std::process::exit(2);
} Type guard
fn is_git_missing(e: &std::io::Error) -> bool {
e.kind() == std::io::ErrorKind::NotFound && e.to_string().contains("git")
} Try / catch
match snapshots::Repo::open(&ws) {
Ok(r) => Ok(r),
Err(e) if is_git_missing(&e) => disable_snapshots_with_notice("install git and restart"),
Err(e) => Err(e),
} Prevention
- Check `which git` inside the exact launch context (service unit, launcher plist), not just your shell
- Bake git into container images rather than assuming the runtime provides it
- Fail fast at startup when a feature that needs git is enabled
When it happens
Trigger: Snapshot pruning/rebuild runs commit-tree while the git executable is not resolvable from the process PATH — git not installed, or the app launched from an environment whose PATH lacks git (GUI launchers, service contexts, minimal containers).
Common situations: macOS launch from Finder/Dock where PATH is the minimal system default; systemd/service or cron launches with sanitized env; distrobox/Nix shells without git in scope; slim Docker images without git installed.
Related errors
- git not found
- no executable search path is configured
- no trusted executable search path remains outside the worksp
- config path cannot be empty
- config path must include a file name
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/cd8c22e95158fa72.
Report an issue: GitHub.