GitoxideLabs/gitoxide · error
the resolved conflict is outside the rebase scope
Error message
the resolved conflict is outside the rebase scope
What it means
If the state records a resolved conflict commit (`resolved`), that commit must be inside the captured rebase scope. A resolved commit outside the scope means the recorded conflict resolution cannot belong to this rebase, so the state is rejected as inconsistent.
Solutions
- Discard the rebase state and restart the rebase to recapture the resolved commit
- Update the `resolved` field to the in-scope ObjectId of the actual resolution
- Avoid running other history-rewriting git commands while a tix rebase is in progress
Defensive patterns
Strategy: validation
Validate before calling
if let Some(resolved) = state.resolved {
assert!(scope.contains(&resolved), "resolved commit must be in scope");
} Try / catch
if let Err(e) = result {
if e.to_string().contains("resolved conflict is outside the rebase scope") {
// abandon state and restart the rebase
}
} Prevention
- Resolve conflicts through the tix workflow, not by editing state
- Avoid reset/GC between interruption and resumption
- Validate state before each resume
When it happens
Trigger: validate_state checks `state.resolved.is_some_and(|id| !scope.contains(&id))`; the bail fires when the `resolved` field of the persisted state holds an ObjectId not present in `state.scope`. Caused by hand-edited state, stale state after external history rewrites, or cross-repo state copies.
Common situations: Resuming an interrupted rebase after a reset/rebase/GC changed commit IDs; manually fixing conflict resolution in the state file.
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 root of a repeated rebase must be pending
- the parent of a repeated rebase must not be pending
- the current checkout has a pending rebase; time-travel to…
- has a pending rebase
- the rebase state contains duplicate scope commits
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/9c23a30fe8048bcf.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/todo.rs:821
}
for tip in &state.tips {
repo.find_commit(*tip).context("could not find a recorded rebase tip")?;
}
for id in &state.scope {
let commit = repo
.find_commit(*id)
.context("could not find a recorded scope commit")?;
let parent = commit
.parent_ids()
.next()
.map(gix::Id::detach)
.context("a recorded scope commit has no parent")?;
if parent != state.base && !scope.contains(&parent) && !continuation_sources.contains(id) {
anyhow::bail!("a recorded scope commit is disconnected from the rebase base");
}
}
if state.resolved.is_some_and(|id| !scope.contains(&id)) {
anyhow::bail!("the resolved conflict is outside the rebase scope");
}
if !continuation_sources.is_subset(&scope) {
anyhow::bail!("a continuation source is outside the rebase scope");
}
Ok(())
}
pub(crate) fn parse(repo: &gix::Repository, edited: &[u8]) -> Result<Option<Parsed>> {
repo.head()?.id().context("rebase todos require a born HEAD")?;
let input = std::str::from_utf8(edited).context("the rebase todo is not UTF-8")?;
let Some(mut state) = parse_state(repo, input)? else {
return Ok(None);
};
let scope: HashSet<_> = state.scope.iter().copied().collect();
let mut picked = HashMap::<ObjectId, usize>::new();
let mut steps = Vec::<rebase::PlanStep>::new();
let mut cursor = None;
let mut checkout_target = None;View on GitHub (pinned to e73179060b)