Hmbown/CodeWhale · error

Failed to run git apply

Error message

Failed to run git apply: {e}

What it means

Raised when the `git apply` subprocess itself fails to launch — `cmd.output()` returns an io::Error (distinct from git running but exiting non-zero, which produces 'git apply failed: <stderr>'). The patch was already written to a temp file at this point; only process startup failed.

Solutions

  1. Retry the apply; transient fork failures often clear under reduced load
  2. Check container/fd/pid limits (ulimit, cgroup pids.max) if failures are repeated
  3. Confirm git remains on PATH and executable for the whole session
  4. Verify the temp directory (TMPDIR) is writable and accessible to git

Example fix

// before
.output()
.map_err(|e| anyhow::anyhow!("Failed to run git apply: {e}"))?;
// after
.output()
.map_err(|e| anyhow::anyhow!("Failed to run git apply: {e} (check git is installed and TMPDIR '{}' is accessible)", std::env::temp_dir().display()))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust
if which::which("git").is_err() {
    bail!("git must be on PATH before running apply");
}
assert!(tmp_path.exists(), "temp patch file missing before git apply");

Try / catch

// Rust
let output = cmd.output()
    .map_err(|e| anyhow::anyhow!("Failed to run git apply: {e}"))?;
if !output.status.success() {
    let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
    bail!("git apply failed: {stderr}");
}

Prevention

When it happens

Trigger: `.output()` errors while spawning `git apply --whitespace=nowarn <tmpfile>` — git disappeared from PATH between check and spawn, exec permission lost, tmpfile path invalid for exec context, or fork/resource exhaustion.

Common situations: Race where the environment changes mid-run; SELinux/AppArmor blocking exec; out-of-memory or PID limits in containers preventing fork; temp file on a mount invisible to the spawned git process.

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


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/c969cf1b45fa1494. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:9921

            .map_err(|e| anyhow::anyhow!("Failed to read patch {}: {}", path.display(), e))?
    } else {
        read_patch_from_stdin()?
    };
    if patch.trim().is_empty() {
        bail!("Patch is empty.");
    }

    let mut tmp = NamedTempFile::new()?;
    tmp.write_all(patch.as_bytes())?;
    let tmp_path = tmp.path().to_path_buf();

    let output = crate::dependencies::Git::command()
        .ok_or_else(|| anyhow::anyhow!("git not found on PATH"))?
        .arg("apply")
        .arg("--whitespace=nowarn")
        .arg(&tmp_path)
        .output()
        .map_err(|e| anyhow::anyhow!("Failed to run git apply: {e}"))?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!("git apply failed: {}", stderr.trim());
    }
    println!("Applied patch successfully.");
    Ok(())
}

/// Maximum bytes read for a patch on stdin. Generous for large diffs;
/// anything larger is not a patch.
const MAX_STDIN_PATCH_BYTES: u64 = 16 * 1024 * 1024;

fn read_patch_from_stdin() -> Result<String> {
    let stdin = io::stdin();
    if stdin.is_terminal() {
        bail!("No patch file provided and stdin is empty.");
    }

View on GitHub (pinned to 73e0f67d83)