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
- Choose a different, unique name for the saved state.
- Delete the existing reference (e.g. `git update-ref -d <name>`) before saving again.
- 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
- Generate unique state names (include a timestamp or hash).
- Check reference existence with try_find_reference before saving.
- Treat named states as immutable and version the name when content changes.
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
- stashes at and would converge on
- Tree conflicted
- File conflicted
- Tree conflicted, refusing to write commit
- Tree conflicted
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)