GitoxideLabs/gitoxide · error

an @ reference requires an @ command at the same result

Error message

an @ reference requires an @ command at the same result

What it means

An `@`-marked entry inside a `(…)` reference line selects where HEAD's checkout is anchored, but it is only valid when a corresponding `@` command also exists in the todo, marking the same step. `parse` throws this error when a reference line contains an `@` entry while no `@` command (and no checkout target derived from one) was parsed.

Solutions

  1. Add an `@`-marked command (`pick @<id>` or `squash @<id>`) at the step the reference should point to.
  2. Remove the `@` prefix from the reference entry in the `(…)` line if no explicit checkout should be selected.
  3. Regenerate the todo via the tool to restore consistent pairing of `@` commands and references.

Example fix

// before
──── fork aaa1 ────
pick bbb2 ...
(@refs/heads/main)

// after (either)
──── fork aaa1 ────
pick @bbb2 ...
(@refs/heads/main)

// or remove the marker:
(refs/heads/main)
Defensive patterns

Strategy: validation

Validate before calling

// Rust: an (@ref) entry requires a corresponding @-marked command somewhere in the todo
let has_at_ref = text.lines().any(|l| l.contains("(@"));
let has_at_cmd = text.lines().any(|l| {
    let t = l.trim();
    (t.starts_with('@') || t.starts_with("`@")) && !t.starts_with("(@")
});
if has_at_ref && !has_at_cmd {
    return Err("an @ reference requires an @ command");
}

Try / catch

match parse_plan(&repo, text) {
    Ok(plan) => apply(plan),
    Err(e) if e.to_string().contains("requires an @ command") => {
        eprintln!("Remove the @ from the reference or add an @-marked command.");
        Err(e)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Writing `(@refs/heads/main)` in a reference line while no command line in the todo carries the `@` marker (the marked command was deleted or its `@` stripped).

Common situations: The user deletes the `@`-marked command line to drop a commit but leaves the `@` on the branch reference; todo templates that carry `@` on refs by default.

Related errors


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

Appendix: source

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

        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 {
                reference.new = None;
                reference.placement = ref_targets.remove(&reference.name);
            }
        }
    }
    let checkout = checkout_target.map(|target| rebase::PlanCheckout {
        target,
        reference: checkout_reference,
    });

View on GitHub (pinned to e73179060b)