GitoxideLabs/gitoxide · error

--to is ambiguous; candidates: travel to one directly with…

Error message

--to {} is ambiguous; candidates:
  {candidates}
travel to one directly with `tix travel REVSPEC`

What it means

The `--to` flag of `tix edit --to` was given a change-id spec that matches more than one commit candidate, so the edit target is ambiguous. The tix command refuses to guess and lists all matching candidates by short change-id. It tells the user to disambiguate by using `tix travel REVSPEC` to land directly on the intended commit first.

Solutions

  1. Use `tix travel REVSPEC` to move to the exact intended commit, then run the edit command without `--to`.
  2. Extend the `--to` value (longer change-id prefix or more specific spec) so it matches exactly one candidate.
  3. Inspect the printed candidate list and pick the correct one explicitly.

Example fix

// before
tix edit --to ab12 fix
// after (ab12abcd and ab12efgh both match)
tix travel ab12abcd && tix edit fix
Defensive patterns

Strategy: validation

Validate before calling

let candidates = resolve_change_id_candidates(&repository, &to)?;
if candidates.len() > 1 {
    eprintln!("--to {} is ambiguous ({} candidates); use tix travel to pick one", to.name(), candidates.len());
    return Ok(());
}

Try / catch

match result {
    Err(e) if e.to_string().contains("is ambiguous") => eprintln!("extend the --to spec to a unique change-id"),
    other => other?,
}

Prevention

When it happens

Trigger: Running an edit-style command with `--to <name>` where `name` resolves via `crate::change_id` to 2+ commits (e.g. a partial change-id prefix or a spec matching several commits) in `relative_destination`, called from `run`.

Common situations: Typing an abbreviated change-id prefix that is no longer unique as new commits were created; reusing similar branch/spec names; having stacked commits from the same change that all match the spec.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at gix-tix/src/command/travel.rs:168

        To::Parent => visible_parents(graph, head, &stored),
        To::Child => order
            .iter()
            .copied()
            .filter(|id| graph.parents_of(*id).is_some_and(|parents| parents.contains(&head)))
            .collect(),
        To::First => first_candidates(graph, head, &stored, &order),
        To::Tip => terminal_candidates(head, &children_by_parent(graph, &stored, &order), &order),
    };
    match candidates.as_slice() {
        [candidate] => Ok(*candidate),
        [] => anyhow::bail!("HEAD has no {} in the default Tix view", to.name()),
        candidates => {
            let candidates = candidates
                .iter()
                .map(|id| crate::change_id::display_short(repository, *id))
                .collect::<Result<Vec<_>>>()?
                .join("\n  ");
            anyhow::bail!(
                "--to {} is ambiguous; candidates:\n  {candidates}\ntravel to one directly with `tix travel REVSPEC`",
                to.name()
            )
        }
    }
}

fn visible_parents(
    graph: &crate::history::HistoryGraph,
    id: gix::ObjectId,
    stored: &HashSet<gix::ObjectId>,
) -> Vec<gix::ObjectId> {
    graph
        .parents_of(id)
        .unwrap_or_default()
        .into_iter()
        .filter(|parent| stored.contains(parent))
        .collect()

View on GitHub (pinned to e73179060b)