GitoxideLabs/gitoxide · error

the rebase state has more than one base

Error message

the rebase state has more than one base

What it means

The state anchor body is a key/value list where `base` may appear at most once. If a second `base` line is found, `parse_state` bails because the rebase's base commit would be ambiguous — the parser refuses to guess which one is authoritative.

Solutions

  1. Remove the duplicate `base` line from the state anchor, keeping the correct oid.
  2. Regenerate the todo/state anchor with tix instead of editing it by hand.
  3. Abort and restart the rebase to get a pristine state block.
  4. Validate the anchor content with `grep -c '^base '` before parsing.

Example fix

// before (inside anchor body)
// base 0123abc...
// base 4567def...
let state = parse_state(repo, text)?; // bails

// after
// base 0123abc...   (single, correct base)
let state = parse_state(repo, &dedupe_state_lines(text))?;
Defensive patterns

Strategy: validation

Validate before calling

// inside the anchor body, before parsing
let base_lines = body.lines().filter(|l| l.starts_with("base ")).count();
if base_lines > 1 {
    anyhow::bail!("state anchor declares base more than once");
}

Try / catch

match parse(repo, todo_text) {
    Ok(s) => s,
    Err(e) if e.to_string().contains("more than one base") => {
        // fix the anchor to a single base line, then retry
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `parse` on a todo whose state anchor contains two `base <oid>` lines — typically from a duplicated or hand-edited state block.

Common situations: Manual editing of the state anchor adding a stray base line; a bad merge/patch duplicating state lines inside one anchor; scripted todo generation emitting base twice.

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

Appendix: source

Thrown at gix-tix/src/edit/todo.rs:685

        anyhow::bail!("the rebase todo contains more than one state anchor");
    }
    let mut base = None;
    let mut onto = None;
    let mut tips = Vec::new();
    let mut scope = Vec::new();
    let mut marker_required = None;
    let mut checkout_allowed = None;
    let mut head_ref = None;
    let mut edit_refs = false;
    let mut expected_refs = Vec::new();
    let mut resolved = None;
    let mut continuation_sources = Vec::new();
    for line in body[..end].lines() {
        let (key, value) = line.split_once(' ').context("a rebase state line has no value")?;
        match key {
            "base" => {
                if base.replace(ObjectId::from_hex(value.as_bytes())?).is_some() {
                    anyhow::bail!("the rebase state has more than one base");
                }
            }
            "onto" => {
                if onto.replace(ObjectId::from_hex(value.as_bytes())?).is_some() {
                    anyhow::bail!("the rebase state has more than one onto target");
                }
            }
            "tip" => tips.push(ObjectId::from_hex(value.as_bytes())?),
            "scope" => scope.push(ObjectId::from_hex(value.as_bytes())?),
            "marker-required" => {
                if marker_required.replace(value.parse()?).is_some() {
                    anyhow::bail!("the rebase state repeats marker-required");
                }
            }
            "checkout-allowed" => {
                if checkout_allowed.replace(value.parse()?).is_some() {
                    anyhow::bail!("the rebase state repeats checkout-allowed");
                }

View on GitHub (pinned to e73179060b)