GitoxideLabs/gitoxide · error

git stash push failed

Error message

git stash push failed: {}

What it means

The external `git stash push --include-untracked --quiet --message` subprocess exited with a non-zero status, so the library aborts the save. The stderr of the git invocation is included in the message. This means the actual stash operation failed before the library could create the named reference.

Solutions

  1. Read the stderr in the error message and fix the underlying git failure it reports.
  2. Remove stale lock files (`.git/index.lock`) left by crashed git processes.
  3. Run `git stash push --include-untracked` manually in the repo to reproduce and diagnose.
  4. Ensure a compatible `git` binary is installed and on PATH.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check for common blockers
if repo.workdir().map(|w| w.join(".git/index.lock").exists()).unwrap_or(false) {
    return Err(anyhow!("index.lock present; another git process may be running"));
}

Try / catch

match save(repo_path, bare, name, msg, reflog) {
    Err(e) if e.to_string().contains("git stash push failed") => {
        eprintln!("git stderr: inspect the chained message");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling save/save_manual, which shells out to `git stash push`; the child process returns non-zero (e.g. nothing to stash in some git configs, lock files, index corruption, git not agreeing to the operation).

Common situations: Another git process holding `.git/index.lock`; a git version whose `stash push` rejects the invocation; dirty submodule/permission problems making stash fail; git binary missing or broken.

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 GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/2b0a2ccfc9ff8617. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/stash.rs:221

    let repo = open_repository(repository_path, bare, false)
        .with_context(|| format!("could not open repository to save {state_label}"))?;
    if repo.try_find_reference(name.as_ref())?.is_some() {
        anyhow::bail!("{state_label} is already saved");
    }
    let previous = repo
        .try_find_reference("refs/stash")?
        .and_then(|mut reference| reference.peel_to_id().ok().map(gix::Id::detach));
    drop(repo);

    let output = Command::new("git")
        .arg("-C")
        .arg(workdir)
        .args(["stash", "push", "--include-untracked", "--quiet", "--message"])
        .arg(message)
        .output()
        .context("could not launch git stash push")?;
    if !output.status.success() {
        anyhow::bail!("git stash push failed: {}", output.stderr.trim().to_str_lossy());
    }

    let repo = open_repository(repository_path, bare, false).context("could not reopen repository after stashing")?;
    let mut stash = repo
        .try_find_reference("refs/stash")?
        .context("git stash push did not create refs/stash")?;
    let id = stash.peel_to_id()?.detach();
    if previous == Some(id) {
        anyhow::bail!("git stash push did not create a new stash");
    }
    let target = Target::Object(id);
    if let Err(err) = repo.edit_references([RefEdit::update(
        name.clone(),
        target.clone(),
        PreviousValue::MustNotExist,
        reflog_message,
    )]) {
        drop(repo);

View on GitHub (pinned to e73179060b)