GitoxideLabs/gitoxide · error
the undo sentinel contains reference changes
Error message
the undo sentinel contains reference changes
What it means
The sentinel commit marks the start of the undo queue and must contain no reference changes — its body is empty configuration. `parse_commit` throws this when a parentless queue commit carries reference changes, which would make undo bookkeeping ambiguous.
Solutions
- Regenerate the sentinel with an empty body by re-initializing the undo queue via the library
- Move any reference changes into a proper child undo operation commit created by `record`
- Avoid editing undo queue commit messages by hand
Defensive patterns
Strategy: try-catch
Try / catch
match undo.load(repo) {
Err(e) if e.to_string().contains("sentinel") => {
// rebuild the undo queue via the library
}
other => other?,
} Prevention
- Never edit undo queue commit messages manually
- Keep sentinel commits bodyless
When it happens
Trigger: Calling `parse_commit` (via `is_queue_commit` or `load`) on a parentless undo queue commit whose parsed config body contains entries.
Common situations: Manually editing a sentinel commit's message to embed changes, or a tool rewriting the queue history and merging changes into the root commit.
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
- an undo queue commit does not use the empty tree
- the undo sentinel has the wrong title
- an undo commit has invalid retention parents
- At least one object couldn't be looked up even though it…
- could not read reference
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/5023aa7821ba777d.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/undo.rs:856
.context("could not own an undo queue commit")?;
ensure!(
commit.tree == ObjectId::empty_tree(repo.object_hash()),
"an undo queue commit does not use the empty tree"
);
let message = gix::objs::commit::MessageRef::from_bytes(&commit.message);
let title = message
.title
.to_str()
.context("an undo operation title is not UTF-8")?
.to_owned();
validate_title(&title)?;
let body = message.body.context("an undo queue commit has no metadata body")?;
let changes = parse_config(repo, body)?;
let parent = commit.parents.first().copied();
match parent {
None => {
ensure!(title == START_TITLE, "the undo sentinel has the wrong title");
ensure!(changes.is_empty(), "the undo sentinel contains reference changes");
}
Some(parent) => {
ensure!(!changes.is_empty(), "an undo operation contains no reference changes");
let expected = retention_parents(repo, parent, &changes)?;
ensure!(
commit.parents.as_slice() == expected,
"an undo commit has invalid retention parents"
);
}
}
Ok(ParsedCommit { parent, title, changes })
}
#[cfg(test)]
mod tests {
use super::*;
fn repo() -> gix_testtools::Result<(gix_testtools::tempfile::TempDir, gix::Repository)> {View on GitHub (pinned to e73179060b)