GitoxideLabs/gitoxide · error

an undo operation contains no reference changes

Error message

an undo operation contains no reference changes

What it means

Each non-sentinel undo operation must record at least one reference change; an operation that changes nothing is meaningless. `parse_commit` throws this when a queue commit with a parent has an empty parsed changes set in its body.

Solutions

  1. Skip recording undo operations when no reference changes were detected
  2. Rebuild the queue entry with a body containing the actual reference changes via the library's `record` path
  3. If the body was edited, restore the original commit message with the change entries

Example fix

// before
if changes.is_empty() { undo.record(repo, title)?; }
// after
if !changes.is_empty() {
    undo.record(repo, title)?;
}
Defensive patterns

Strategy: validation

Validate before calling

if changes.is_empty() {
    // skip recording an undo operation entirely
    return Ok(());
}

Prevention

When it happens

Trigger: Calling `parse_commit` (via `is_queue_commit` or `load`) on a non-root undo queue commit whose message body parses to an empty set of reference changes.

Common situations: Recording an undo when no references actually changed (e.g. a no-op operation), or a commit whose body was truncated/edited so changes were lost.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/d8b0762fd5bed87b. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/undo.rs:859

        "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)> {
        let fixture = gix_testtools::scripted_fixture_writable("create_commit.sh")?;
        let repository = crate::test_repository::open(fixture.path())?;
        Ok((fixture, repository))

View on GitHub (pinned to e73179060b)