GitoxideLabs/gitoxide · error · anyhow::Error
an undo entry requires the exact previous reference value
Error message
an undo entry requires the exact previous reference value
What it means
Conversion failure in `edit::undo::state_from_expected`, called from `from_edit` when building undo queue state from a planned reference change. A `PreviousValue` expresses what a ref must have looked like before the edit; only `MustNotExist`, `MustExistAndMatch(target)` map cleanly onto an undo State. The wildcard variants (`Any`, `MustExist`, `Existing...`) carry no concrete value to restore, so an exact previous value cannot be recorded and the conversion bails. It indicates an undo entry was planned against a reference whose pre-edit value was not pinned; fix by ensuring the edit pins the exact expected prior ref value before it can be undone.
Solutions
- Record the undo entry against the reference's actual current value so the expected PreviousValue matches what the repository contains
- Regenerate the undo queue (drop the stale entries) so subsequent expectations are rebuilt from the real reference states
- If the reference's prior value is genuinely unknown, use PreviousValue::Any rather than asserting a specific prior state
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at gix-tix/src/edit/undo.rs:370 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/9490ee9cf29e6ff8.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/undo.rs:370
existing.after = change.after;
}
None => {
by_name.insert(change.name.clone(), change);
}
}
}
Ok(by_name
.into_values()
.filter(|change| change.before != change.after)
.collect())
}
fn state_from_expected(expected: &PreviousValue) -> Result<State> {
match expected {
PreviousValue::MustNotExist => Ok(State::Missing),
PreviousValue::MustExistAndMatch(target) => Ok(state_from_target(target)),
PreviousValue::Any | PreviousValue::MustExist | PreviousValue::ExistingMustMatch(_) => {
bail!("an undo entry requires the exact previous reference value")
}
}
}
fn state_from_target(target: &Target) -> State {
match target {
Target::Object(id) => State::Object(*id),
Target::Symbolic(name) => State::Symbolic(name.clone()),
}
}
fn state_from_target_ref(target: gix::refs::TargetRef<'_>) -> State {
match target {
gix::refs::TargetRef::Object(id) => State::Object(id.to_owned()),
gix::refs::TargetRef::Symbolic(name) => State::Symbolic(name.to_owned()),
}
}
View on GitHub (pinned to e73179060b)