GitoxideLabs/gitoxide · error

undo metadata must start with [undo]

Error message

undo metadata must start with [undo]

What it means

Undo queue commits store their metadata as a Git config blob inside the commit. `parse_config` requires the very first config section to be `[undo]` with no subsection — this anchors and versions the metadata format. A commit whose config blob starts with any other section (or a subsectioned `[undo "x"]`) is not a valid undo-metadata commit, so this error is raised.

Solutions

  1. Check what the queue refs point at (`git cat-file -p <tip>`) — if they point at non-undo commits, reset the queue refs to valid undo commits or discard the queue.
  2. Regenerate the queue via the library's record/reset APIs instead of writing queue commits by hand.
  3. Restore the queue from a backup where the metadata was valid.

Example fix

// before: hand-built queue commit body
"[core]\n\tfoo = bar\n"
// after: metadata must open with the [undo] version section
"[undo]\n\tversion = 1\n" // plus the recorded ref changes
Defensive patterns

Strategy: validation

Validate before calling

// verify queue refs point at genuine undo-metadata commits before undo/redo
let commit = repo.find_object(tip_id)?;
let body = extract_config_body(&commit);
let ok = body.starts_with(b"[undo]");
if !ok { anyhow::bail!("queue tip is not an undo-metadata commit; reset the queue"); }

Prevention

When it happens

Trigger: `parse_commit` -> `parse_config` when the referenced queue commit's config body has a different leading section, e.g. queue refs pointing at ordinary commits or hand-built queue commits with the wrong config layout.

Common situations: Manually crafted queue commits; queue refs pointing at unrelated commits (e.g. after ref juggling or restore from backup); third-party tools writing to the queue refs with their own format.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

}

fn encode_state(state: &State) -> BString {
    match state {
        State::Missing => "missing".into(),
        State::Object(id) => format!("object:{id}").into(),
        State::Symbolic(name) => {
            let mut value = BString::from("symbolic:");
            value.extend_from_slice(name.as_bstr());
            value
        }
    }
}

fn parse_config(repo: &gix::Repository, body: &BStr) -> Result<Vec<RefChange>> {
    let config = File::try_from(body).context("could not parse undo metadata as Git config")?;
    let mut sections = config.sections();
    let undo = sections.next().context("undo metadata has no version section")?;
    ensure!(
        undo.header().name() == b"undo" && undo.header().subsection_name().is_none(),
        "undo metadata must start with [undo]"
    );
    ensure_exact_keys(&undo, &["version"])?;
    ensure!(
        undo.value("version").as_ref().map(|value| value.as_slice()) == Some(VERSION.as_bytes()),
        "unsupported undo metadata version"
    );

    let mut changes = Vec::new();
    let mut previous_name: Option<FullName> = None;
    for section in sections {
        ensure!(
            section.header().name() == b"ref",
            "undo metadata contains an unknown section"
        );
        let subsection = section
            .header()

View on GitHub (pinned to e73179060b)