GitoxideLabs/gitoxide · error
undo metadata contains an unknown section
Error message
undo metadata contains an unknown section
What it means
When tix restores or inspects undo state, it parses the stored undo metadata as a Git config file. After the leading `[undo]` version section, every remaining section must be a `[ref "<name>"]` section describing one reference change. This error is raised when any subsequent section has a header name other than `ref`, meaning the metadata file was hand-edited, corrupted, or written by an incompatible version of tix.
Solutions
- Inspect the undo metadata and remove or fix any section whose header is not `[ref "<reference-name>"]`
- Regenerate the undo metadata by re-running the operation that produced it, or clear the undo state and redo the ref changes manually
- Check for merge-conflict markers in the metadata if it was touched by a merge
- Ensure all tix versions used against the repository are from the same compatible release
Example fix
// before (corrupt metadata body) [undo] version = v1 [ref "refs/heads/main"] before = missing after = object:abc123 [stale] key = value // after [undo] version = v1 [ref "refs/heads/main"] before = missing after = object:abc123
Defensive patterns
Strategy: validation
Validate before calling
// before reading undo state, validate the metadata body
let config = gix::config::File::try_from(body.as_ref())?;
let mut sections = config.sections();
let undo = sections.next().ok_or("missing [undo] header")?;
assert_eq!(undo.header().name(), b"undo");
for s in sections {
assert_eq!(s.header().name(), b"ref", "unknown section {:?}", s.header().name());
} Type guard
fn is_ref_section(header: &gix::config::file::Header<'_>) -> bool {
header.name() == b"ref" && header.subsection_name().is_some()
} Try / catch
match load_undo_state(&repo) {
Ok(changes) => apply(changes),
Err(e) if e.to_string().contains("unknown section") => {
eprintln!("undo metadata corrupt; resetting undo state");
reset_undo_state(&repo)?;
}
Err(e) => return Err(e),
} Prevention
- Never hand-edit the undo metadata ref; use tix commands
- Check for merge-conflict markers if the metadata ref was touched by a merge
- Keep all tix installations on a compatible version
- Validate the metadata body after any external tool touches refs
When it happens
Trigger: Calling any undo/redo flow that reaches `parse_config` (via `parse_commit`) while the stored undo metadata body contains a section like `[other]` or `[refextra "..."]` after the `[undo]` header — typically from manual editing of the metadata ref, a merge conflict inside it, or tampering.
Common situations: A developer edits the undo metadata ref (or a merge leaves conflict markers in it), an old tix version wrote a different section layout, or an external tool rewrote the refs storage.
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
- the undo queue records itself
- undo reference sections are duplicated or out of order
- the undo queue is not a selectable revision
- an undo operation title cannot be empty
- an undo operation title must be one line
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/0a87e05249ea0e08.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/undo.rs:612
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()
.subsection_name()
.context("an undo ref section has no reference name")?;
let name = FullName::try_from(subsection).context("an undo entry contains an invalid reference name")?;
ensure!(!is_queue_ref(name.as_bstr()), "the undo queue records itself");
if let Some(previous) = &previous_name {
ensure!(
previous < &name,
"undo reference sections are duplicated or out of order"
);
}
previous_name = Some(name.clone());
ensure_exact_keys(§ion, &["before", "after"])?;
let before = section.value("before").context("an undo ref has no before-state")?;View on GitHub (pinned to e73179060b)