GitoxideLabs/gitoxide · error

cannot spill an unmerged path

Error message

cannot spill an unmerged path

What it means

`spill_paths_tree` rebuilds a tree that undoes selected path changes from a commit, but an `Unmerged` path change (a merge conflict with multiple index stages) has no single well-defined content to restore. The library bails out instead of guessing which stage to spill. Resolve the conflict first so the path has a definite entry.

Solutions

  1. Resolve the conflicted path in the worktree/index and create a new commit containing the resolution, then retry the spill.
  2. Abort the operation and clean the conflict state with `git status`/`git restore --staged` before re-running tix.
  3. Check the source commit for conflict markers or unmerged entries (`git ls-files -u`) before spilling.

Example fix

// before: spilling a commit built on an unmerged index
// error: cannot spill an unmerged path

// after: resolve first
git checkout --theirs path && git add path && git commit -m "resolve"
# then retry the tix spill
Defensive patterns

Strategy: validation

Validate before calling

// Rust: skip or reject unmerged changes before spilling
if changes.iter().any(|c| c.kind == ChangeKind::Unmerged) {
    anyhow::bail!("resolve conflicts before spilling");
}

Type guard

fn spillable(c: &PathChange) -> bool {
    c.kind != ChangeKind::Unmerged
}

Prevention

When it happens

Trigger: Spilling changes off a commit when the commit's diff contains an entry whose `ChangeKind` is `Unmerged` — typically a commit created from an index that still contains conflict stages, or a conflict recorded in history comparisons.

Common situations: A commit was made while the index still held unmerged stages (e.g. via `git commit -a` after a conflicted merge with unresolved entries forced through), and the user later tries to spill/revert those paths in tix.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at gix-tix/src/edit/head.rs:282

            ChangeKind::Added => {
                editor.remove(&change.path).context("could not spill the added path")?;
            }
            ChangeKind::Deleted | ChangeKind::Modified | ChangeKind::TypeChanged => {
                restore_path(&parent, &mut editor, &change.path)?;
            }
            ChangeKind::Renamed | ChangeKind::Copied => {
                editor
                    .remove(&change.path)
                    .context("could not spill the rewritten destination")?;
                if change.kind == ChangeKind::Renamed {
                    restore_path(
                        &parent,
                        &mut editor,
                        change.source.as_ref().context("a rename has no source path")?,
                    )?;
                }
            }
            ChangeKind::Unmerged => anyhow::bail!("cannot spill an unmerged path"),
        }
    }
    Ok(editor
        .write()
        .context("could not build the partially spilled tree")?
        .detach())
}

fn restore_path(
    parent: &gix::Tree<'_>,
    editor: &mut gix::object::tree::Editor<'_>,
    path: &gix::bstr::BString,
) -> Result<()> {
    let entry = parent
        .lookup_entry(
            path.split(|byte| *byte == b'/')
                .map(|component| BStr::new(component).to_owned()),
        )

View on GitHub (pinned to e73179060b)