nikivdev/code · error

failed to stash working tree: {}

Error message

failed to stash working tree: {}

What it means

Thrown by stash_if_dirty (src/changes.rs:766) when `git stash push -u -m <msg>` exits non-zero while preparing a dirty working tree before unrolling a bundle. The message carries git's trimmed stderr, so it reflects the underlying git failure (not a Rust-side fault).

Source

Thrown at src/changes.rs:766

    let (status, _ok) = git_output_in(repo_root, &["status", "--porcelain"])?;
    if status.trim().is_empty() {
        trace("working tree clean; no stash needed");
        return Ok(None);
    }

    let message = format!(
        "flow-diff-{}-{}",
        &bundle_hash[..bundle_hash.len().min(8)],
        Utc::now().format("%Y%m%d-%H%M%S")
    );
    let output = Command::new("git")
        .current_dir(repo_root)
        .args(["stash", "push", "-u", "-m", &message])
        .output()
        .context("failed to stash working tree")?;
    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!("failed to stash working tree: {}", stderr.trim());
    }

    let (stash_ref, _ok) = git_output_in(repo_root, &["stash", "list", "-1", "--pretty=%gd"])?;
    let stash_ref = stash_ref.trim().to_string();
    if stash_ref.is_empty() {
        return Ok(Some(message));
    }

    record_stash(repo_root, &stash_ref, bundle_hash, &message)?;
    Ok(Some(stash_ref))
}

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the stderr suffix in the message and fix the underlying git error it names (e.g. remove a stale .git/index.lock).
  2. Run `git stash push -u -m test` manually in the repo root to reproduce and see the full git error.
  3. Confirm repo_root is actually a git work tree (`git -C <root> rev-parse --is-inside-work-tree`).
  4. Commit or clean uncommitted changes manually, then retry the unroll so stashing is skipped.
  5. Check git version and hooks (gpg signing, smudge/clean filters) that could fail during stash.

Example fix

// before
Error: failed to stash working tree: fatal: Unable to create '.../.git/index.lock': File exists.
// after
$ rm .git/index.lock
$ f unroll <bundle>  # stash succeeds
Defensive patterns

Strategy: try-catch

Validate before calling

// Shell: preconditions before running a stashing command
git -C "$REPO" rev-parse --is-inside-work-tree || exit 1
[ -f "$REPO/.git/index.lock" ] && { echo "stale index.lock"; exit 1; }
git -C "$REPO" status --porcelain | head -1  # ensure git itself is healthy

Try / catch

if let Err(e) = unroll_bundle(repo_root, &bundle) {
    if e.to_string().starts_with("failed to stash working tree") {
        // surface git stderr; advise committing changes manually first
        eprintln!("Fix git state per the error, or commit/stash manually and retry.");
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: unroll_bundle calls stash_if_dirty on a repo with uncommitted changes; the git stash subprocess fails — typically because repo_root is not a git work tree, git is missing/old, lock files exist (.git/index.lock), or untracked-file staging fails.

Common situations: Running the command inside a subdirectory project whose parent repo state is broken; concurrent git operations leaving an index.lock; corrupt .git after an interrupted process; custom gpg/signing hooks failing on stash; git not on PATH.

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 nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/96ec74fef33d6812. Report an issue: GitHub.