GitoxideLabs/gitoxide · error

is already saved

Error message

{state_label} is already saved

What it means

This error means a reference with the given name already exists in the repository, so the stash/state cannot be saved under that name. The library throws it before performing any edit, because saving would need `PreviousValue::MustNotExist` and a pre-existing ref would fail the ref-edit. It is a guard against silently overwriting an existing saved state.

Solutions

  1. Choose a different, unique name for the saved state.
  2. Delete the existing reference (e.g. `git update-ref -d <name>`) before saving again.
  3. Check `try_find_reference` for existence first and branch on it instead of calling save unconditionally.

Example fix

// before
let saved = save(repo_path, bare, "my-stash", message, ...)?;
// after
if try_state_exists(repo_path, bare, "my-stash")? {
    eprintln!("my-stash already exists; picking a new name");
}
let saved = save(repo_path, bare, format!("my-stash-{timestamp}"), message, ...)?;
Defensive patterns

Strategy: validation

Validate before calling

let repo = gix::open(repo_path)?;
if repo.try_find_reference(name.as_ref())?.is_some() {
    // pick another name or delete the existing ref first
}

Try / catch

match result {
    Err(e) if e.to_string().ends_with("is already saved") => choose_new_name(),
    other => other?,
}

Prevention

When it happens

Trigger: Calling save (e.g. via save_manual) with a `name` argument for which `repo.try_find_reference(name)` already resolves to an existing reference. Running the same named save twice without deleting or renaming the first one.

Common situations: Re-running a failed or interrupted workflow that had already saved the state under the same name; scripts hardcoding a fixed state name; users manually creating a ref that collides with the tool's state name.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/e0ca85eb7519ae2b. Report an issue: GitHub.

Appendix: source

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

    pub name: gix::refs::FullName,
    pub target: Target,
    pub warning: Option<String>,
}

#[tracing::instrument(skip_all, fields(stash = %name))]
pub(super) fn save(
    repository_path: &Path,
    bare: bool,
    workdir: &Path,
    name: gix::refs::FullName,
    message: String,
    reflog_message: &'static str,
    state_label: &'static str,
) -> Result<SavedStash> {
    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")?;

View on GitHub (pinned to e73179060b)