GitoxideLabs/gitoxide · error

the @ command and @ reference point to different results

Error message

the @ command and @ reference point to different results

What it means

Thrown when both the `@`-marked command and an `@`-style reference in the todo resolve to different plan steps. The single checkout target must be consistent: the marker and any `@` reference to it must point at the same resulting step.

Solutions

  1. Make the `@` reference and the `@`-marked command point at the same step
  2. Keep only one `@` marker and update all references to match its result
  3. Regenerate the todo instead of hand-editing marker placement

Example fix

// before
@pick abc123
pick def456
squash ghi789 @  # refers to a different result
// after
pick abc123
@pick def456
squash ghi789 @  # now consistent
Defensive patterns

Strategy: validation

Validate before calling

// ensure every @ reference resolves to the same step as the single @-marked command
if marked_lines.len() > 1 || (marked_command_line != referenced_line) {
    anyhow::bail!("@ marker and @ reference must point at the same result");
}

Type guard

fn targets_consistent(marker_step: usize, reference_step: Option<usize>) -> bool {
    reference_step.map_or(true, |r| r == marker_step)
}

Try / catch

match parse_plan(...) {
    Err(e) if e.to_string().contains("point to different results") => { /* realign marker and reference */ }
    other => other?,
}

Prevention

When it happens

Trigger: `parse_plan` processes an `@`-marked squash or command whose computed `PlanParent::Step(index)` differs from a previously recorded `checkout_target`.

Common situations: Marking one command with `@` while an `@` reference elsewhere in the todo points at another command's result; hand-editing that moved the marker without moving the reference.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

            }
        }
        if verb == "squash" {
            let index = section_last_step.context("a squash must follow a command in the same fork")?;
            let id = resolve_commit(
                repo,
                value.split_whitespace().next().context("a squash needs a commit ID")?,
            )?;
            if !scope.contains(&id) {
                anyhow::bail!("a squash is outside the editable history");
            }
            if picked.insert(id, index).is_some() {
                anyhow::bail!("a commit is picked more than once");
            }
            steps[index].squash.push(id);
            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;
            continue;
        }
        let parent = cursor.context("the first todo command must follow a fork heading")?;
        let commit = match verb {
            "pick" => {
                let value = value.split_whitespace().next().context("a pick needs a commit ID")?;
                let resolved_id = state.resolved;
                let full_null = resolved_id.is_some_and(|id| {
                    value.len() == id.kind().len_in_bytes() * 2 && value.bytes().all(|byte| byte == b'0')
                });
                let (id, resolved) = if full_null {
                    (
                        resolved_id.context("a null pick has no materialized conflict state")?,
                        true,

View on GitHub (pinned to e73179060b)