GitoxideLabs/gitoxide · error
review requires a clean index and worktree
Error message
review requires a clean index and worktree
What it means
Starting or finishing a review requires a clean index and worktree, because review setup rewrites HEAD, the index, and possibly the worktree via git plumbing. `ensure_clean` runs `git status --porcelain` and refuses to proceed if any entry is reported.
Solutions
- Commit or stash your changes (`git stash -u` to include untracked files), then retry.
- Add intended files and commit them (`git add -A && git commit`).
- Discard unwanted changes explicitly (`git checkout -- . && git clean -fd`) if they are disposable.
Example fix
// before review::start(repo, ...)?; // fails on dirty worktree // after: clean first, then start // git stash -u review::start(repo, ...)?;
Defensive patterns
Strategy: validation
Validate before calling
let status = std::process::Command::new("git")
.args(["status", "--porcelain=v1", "--untracked-files=all"])
.output()?;
if !status.stdout.is_empty() {
return Err(anyhow::anyhow!("commit or stash changes before starting a review"));
} Prevention
- Adopt a habit of `git status` before running review commands.
- Use `git stash -u` to sweep untracked files before review operations.
- Configure editor/build artifacts as gitignored so they never dirty the tree.
When it happens
Trigger: Calling review `start` or `finish_with_progress` while there are unstaged modifications, staged changes, or untracked files in the worktree.
Common situations: Uncommitted edits from ordinary development left in the tree; editor or build artifacts that are untracked; ignored-but-not-ignored generated files; a partially staged change forgotten from an earlier session.
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
- the squash source must have exactly one parent
- Tried to use as tree, but was
- Tried to use as commit, but was
- Tried to use as tag, but was
- invalid mode change: can't flip executable bit of
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/3aff46f3ee253e9c.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/review.rs:320
checkout,
report,
)? {
super::rebase::Perform::Complete(outcome) => {
let finished = outcome
.map(review)
.context("finishing review did not produce a commit")?;
Ok(Finish::Complete(Finished {
commit: finished,
outcome,
}))
}
super::rebase::Perform::Conflict(conflict) => Ok(Finish::Conflict(conflict)),
}
}
pub(super) fn ensure_clean(workdir: &Path) -> Result<()> {
if is_dirty(workdir)? {
anyhow::bail!("review requires a clean index and worktree");
}
Ok(())
}
pub(super) fn is_dirty(workdir: &Path) -> Result<bool> {
let output = Command::new("git")
.arg("-C")
.arg(workdir)
.args(["status", "--porcelain=v1", "--untracked-files=all"])
.output()
.context("could not inspect worktree status")?;
if !output.status.success() {
anyhow::bail!("{}", String::from_utf8_lossy(&output.stderr).trim());
}
Ok(!output.stdout.is_empty())
}
fn next_reference(repo: &gix::Repository) -> Result<gix::refs::FullName> {View on GitHub (pinned to e73179060b)