GitoxideLabs/gitoxide · error

the current checkout marker must be retained

Error message

the current checkout marker must be retained

What it means

When the ongoing rebase already had a checkout marker (HEAD detached at a todo step), the edited todo must retain exactly one `@`-marked command so the checkout position is preserved. If `state.marker_required` is set and no `@`-prefixed command (or `@`-marked reference) remains in the todo, `parse` fails with this error to prevent silently dropping the checkout marker.

Solutions

  1. Re-add the `@` prefix to the command representing the step where HEAD should stay checked out.
  2. Mark a `(ref …)` line with `@` so the checkout is carried by the reference placement instead.
  3. If the checkout is intentionally obsolete, restart the rebase/todo edit from the tool rather than hand-editing.

Example fix

// before
──── fork aaa1 ────
pick bbb2 ...

// after (marker restored)
──── fork aaa1 ────
pick @bbb2 ...
Defensive patterns

Strategy: validation

Validate before calling

// Rust: if the tool flagged a required checkout marker, verify one `@` command exists
let has_marked = text.lines().any(|l| {
    let t = l.trim();
    t.starts_with("@") || t.starts_with("`@") || t.contains("(@")
});
if marker_required && !has_marked {
    return Err("keep one @-marked command to retain the checkout");
}

Try / catch

match parse_plan(&repo, text) {
    Ok(plan) => apply(plan),
    Err(e) if e.to_string().contains("checkout marker must be retained") => {
        eprintln!("Re-add the @ marker to the step where HEAD is checked out.");
        Err(e)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Editing a todo mid-rebase where HEAD is checked out at a step, and the user removes the `@` prefix from the marked `pick @...`/`squash @...` command or deletes that line entirely.

Common situations: A user cleans up `@` marks thinking they are noise; a global find-and-replace strips `@`; a hand-crafted todo omits the marker that a continuing rebase requires.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

        cursor = Some(rebase::PlanParent::Step(index));
        section_last_step = Some(index);
        if marked {
            let target = rebase::PlanParent::Step(index);
            if checkout_target.is_some_and(|checkout| checkout != target) {
                anyhow::bail!("the @ command and @ reference point to different results");
            }
            checkout_target = Some(target);
        }
        section_has_commit = true;
    }
    if sections == 0 {
        anyhow::bail!("the rebase todo has no fork heading");
    }
    if sections > 1 && !section_has_commit {
        anyhow::bail!("the last fork section contains no commits");
    }
    if state.marker_required && checkout_target.is_none() {
        anyhow::bail!("the current checkout marker must be retained");
    }
    let checkout_reference = match (checkout_target, explicit_checkout_reference) {
        (Some(target), Some((name, reference_target))) => {
            if target != reference_target {
                anyhow::bail!("the @ command and @ reference point to different results");
            }
            Some(name)
        }
        (None, Some(_)) => anyhow::bail!("an @ reference requires an @ command at the same result"),
        (Some(target), None) => state
            .head_ref
            .take()
            .filter(|name| ref_targets.get(name) == Some(&target)),
        (None, None) => None,
    };
    if state.edit_refs {
        for reference in &mut state.expected_refs {
            if reference.editable {

View on GitHub (pinned to e73179060b)