GitoxideLabs/gitoxide · error

undo metadata has missing, repeated, or unknown keys

Error message

undo metadata has missing, repeated, or unknown keys

What it means

`ensure_exact_keys` compares the section's actual value names against the exact expected list and rejects any mismatch: a missing key, a duplicated key, or an extra unknown key. This enforces a strict schema for undo metadata sections so parsing downstream can assume every expected key exists exactly once.

Solutions

  1. Make each section contain exactly the expected keys, each once: `before` and `after`, with no extras.
  2. Fix typos in key names (`befor` -> `before`).
  3. Remove obsolete/unknown keys added by other tool versions.
  4. Regenerate the undo metadata with the writing tool rather than hand-editing; if new keys are legitimate, update the expected list in `ensure_exact_keys`.

Example fix

// before
[undo-ref "refs/heads/main"]
	befor = object:1a2b3c...
	after = object:9f8e7d...
	comment = note
// after
[undo-ref "refs/heads/main"]
	before = object:1a2b3c...
	after = object:9f8e7d...
Defensive patterns

Strategy: validation

Validate before calling

fn section_keys_valid(section: &gix::config::file::SectionRef<'_>) -> bool {
    let names: Vec<_> = section.value_names().collect();
    names == ["before", "after"]
}

Try / catch

match parse_undo_metadata(&repo, &text) {
    Err(e) if e.to_string().contains("undo metadata has missing, repeated, or unknown keys") => {
        eprintln!("Each section needs exactly one `before` and one `after` key, no extras");
    }
    res => res?,
}

Prevention

When it happens

Trigger: `parse_config` calls `ensure_exact_keys(&section, &["before", "after"])` (undo.rs:642) on a section that lacks one of the keys, repeats a key, or contains additional keys such as a typo (`befor`) or a comment-like unknown entry.

Common situations: Hand-editing the undo metadata and misspelling `before`/`after`; an older or newer tool version writing extra fields; accidentally duplicating a key when editing; copy-pasting sections and leaving stray keys behind.

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/7a0be7c054beac4f. Report an issue: GitHub.

Appendix: source

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

                previous < &name,
                "undo reference sections are duplicated or out of order"
            );
        }
        previous_name = Some(name.clone());
        ensure_exact_keys(&section, &["before", "after"])?;
        let before = section.value("before").context("an undo ref has no before-state")?;
        let before = parse_state(repo, before.as_bstr())?;
        let after = section.value("after").context("an undo ref has no after-state")?;
        let after = parse_state(repo, after.as_bstr())?;
        ensure!(before != after, "an undo ref does not change");
        changes.push(RefChange { name, before, after });
    }
    Ok(changes)
}

fn ensure_exact_keys(section: &gix::config::file::SectionRef<'_>, expected: &[&str]) -> Result<()> {
    let actual: Vec<_> = section.value_names().collect();
    ensure!(
        actual == expected,
        "undo metadata has missing, repeated, or unknown keys"
    );
    Ok(())
}

fn parse_state(repo: &gix::Repository, value: &BStr) -> Result<State> {
    if value == b"missing" {
        return Ok(State::Missing);
    }
    if let Some(hex) = value.strip_prefix(b"object:") {
        let id = ObjectId::from_hex(hex).context("an undo object ID is invalid")?;
        ensure!(
            id.kind() == repo.object_hash(),
            "an undo object ID uses the wrong hash kind"
        );
        return Ok(State::Object(id));
    }

View on GitHub (pinned to e73179060b)