GitoxideLabs/gitoxide · error
cannot stash changes with unresolved index conflicts
Error message
cannot stash changes with unresolved index conflicts
What it means
Tix refuses to stash changes while the index still contains unresolved merge-conflict entries. Stashing would have to serialize conflict stages, which the save format does not support, so `save_manual` scans index entries and bails if any entry's stage is not `Unconflicted`. This prevents silently losing conflict information.
Solutions
- Resolve the conflicts (`git add` resolved files or `git mergetool`) and then stash
- Abort the in-progress merge/rebase (`git merge --abort`, `git rebase --abort`) to clear conflict stages, then stash
- Check `git status` for "Unmerged paths" and clear them before invoking the stash
Example fix
// before stashing with conflicts
stash::save_manual(path, bare, workdir, head_id)?;
// after: verify the index is unconflicted
let repo = gix::open(path)?;
let clean = repo.index_or_empty()?.entries().iter()
.all(|e| e.stage() == gix::index::entry::Stage::Unconflicted);
assert!(clean, "resolve conflicts before stashing");
stash::save_manual(path, bare, workdir, head_id)?; Defensive patterns
Strategy: validation
Validate before calling
let repo = gix::open(path)?;
let conflicted = repo.index_or_empty()?.entries().iter()
.any(|e| e.stage() != gix::index::entry::Stage::Unconflicted);
if conflicted {
anyhow::bail!("resolve index conflicts before stashing");
} Prevention
- Run `git status` and ensure no "Unmerged paths" before stashing
- Finish or abort in-progress merges/rebases/cherry-picks before stash automation runs
- Add an index-stage check as a gate in scripts that call tix stash
When it happens
Trigger: Calling `stash::save_manual` (or the CLI `tix stash` equivalent) while the repository has conflicted index entries, i.e. after a merge/rebase/cherry-pick that produced conflicts and before they are resolved.
Common situations: Trying to stash mid-merge to "clean up" the worktree; interrupted rebases leaving stage-2/3 entries; cherry-picks with conflicts.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- invalid mode change: can't flip executable bit of
- visit_non_tree() called us
- cannot create a commit with unresolved index conflicts
- {}
- cannot spill an unmerged path
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/e8661eebcd31e9a5.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/stash.rs:139
let workdir = repo
.workdir()
.context("stashing changes requires a worktree")?
.to_owned();
let head = repo
.head_id()
.context("stashing changes requires a born HEAD")?
.detach();
if head != id {
anyhow::bail!("changes can only be stashed at the current HEAD");
}
if repo
.index_or_empty()
.context("could not inspect the index before stashing")?
.entries()
.iter()
.any(|entry| entry.stage() != gix::index::entry::Stage::Unconflicted)
{
anyhow::bail!("cannot stash changes with unresolved index conflicts");
}
let name = reference(id)?;
if repo.try_find_reference(name.as_ref())?.is_some() {
anyhow::bail!("{} already has saved worktree state", id.to_hex_with_len(7));
}
drop(repo);
if !super::review::is_dirty(&workdir)? {
anyhow::bail!("there are no worktree or index changes to stash");
}
let saved = save(
repository_path,
bare,
&workdir,
name,
format!("tix {}", id.to_hex_with_len(7)),
"tix commit stash",
"commit state",
)?;View on GitHub (pinned to e73179060b)