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

  1. Regenerate the sentinel with an empty body by re-initializing the undo queue via the library
  2. Move any reference changes into a proper child undo operation commit created by `record`
  3. 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

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


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)