GitoxideLabs/gitoxide · error

could not retain ; original state was restored

Error message

could not retain {state_label}; original state was restored

What it means

In gix-tix `stash save`, when persisting the new stash state fails, the code attempts a recovery via `git stash pop --index` to restore the user's original working-tree state. If the pop succeeds, the primary error is augmented with "could not retain {state_label}; original state was restored" — telling the user the operation failed but nothing was lost. If the pop also fails, a harsher message including git's stderr is used.

Solutions

  1. Verify your working tree is back to the original state (git status) before retrying
  2. Fix the root cause from the primary error (permissions, disk space) and retry the save
  3. If state was NOT restored (the alternate message), resolve manually with git stash list/pop
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm the working tree is clean/restored before retrying a stash save
let status = Command::new("git").args(["-C", workdir, "status", "--porcelain"]).output()?;
let restored = String::from_utf8_lossy(&status.stdout).trim().is_empty();

Try / catch

match save_state(...) {
    Err(e) if e.to_string().contains("original state was restored") => {
        eprintln!("save failed but your changes are back in the worktree; safe to retry");
    }
    Err(e) => return Err(e),
    Ok(v) => v,
}

Prevention

When it happens

Trigger: Any failure of the stash-save operation (error variable `err`) during `save`/`save_manual` while a real worktree is checked out, followed by a successful `git stash pop --index` recovery.

Common situations: Disk/permission failures while creating the stash; conflicts preventing the restore path; environments where shelling out to `git` behaves differently than expected.

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/fdc58d217cd653e2. Report an issue: GitHub.

Appendix: source

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

        .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);
        let restore = Command::new("git")
            .arg("-C")
            .arg(workdir)
            .args(["stash", "pop", "--index", "--quiet"])
            .output();
        return Err(anyhow::anyhow!(err)).context(match restore {
            Ok(output) if output.status.success() => {
                format!("could not retain {state_label}; original state was restored")
            }
            Ok(output) => format!(
                "could not retain {state_label} and git stash pop failed: {}",
                output.stderr.trim().to_str_lossy()
            ),
            Err(restore) => {
                format!("could not retain {state_label} and could not launch git stash pop: {restore}")
            }
        });
    }
    drop(repo);

    let warning = match current(repository_path, bare)? {
        Some(current) if current == id => {
            let output = Command::new("git")
                .arg("-C")

View on GitHub (pinned to e73179060b)