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
- Add an `@`-marked command (`pick @<id>` or `squash @<id>`) at the step the reference should point to.
- Remove the `@` prefix from the reference entry in the `(…)` line if no explicit checkout should be selected.
- 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 deleting an `@`-marked command, also unmark the matching `(@ref)` entry.
- Remember `@` on a reference line only works alongside an `@` command.
- Prefer letting the tool generate the todo instead of adding markers manually.
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
- the current checkout marker must be retained
- a fork section contains no commits
- a fork target must be picked before it is used
- a reference is placed more than once
- the rebase todo cannot select a checkout without a worktree
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)