GitoxideLabs/gitoxide · error
exactly one time-travel destination is required
Error message
exactly one time-travel destination is required
What it means
`tix travel` accepts exactly one destination argument (absolute OID or relative spec like ^, ~, first, tip). Passing zero or multiple destinations makes the request ambiguous, so run() bails before performing any time travel.
Solutions
- Pass exactly one destination: an OID or a relative target (e.g. `^`, `~2`, `first`, `tip`)
- Quote variables in shell scripts so an empty value yields zero args deliberately and OIDs stay one argument
- Check `tix log`/`tix history` for the correct single target first
Example fix
// before tix travel $A $B // after tix travel "$A"
Defensive patterns
Strategy: validation
Validate before calling
// Validate destination count before invoking
let dests: Vec<&str> = args.to.iter().collect();
if dests.len() != 1 {
return Err(anyhow!("pass exactly one travel destination"));
} Try / catch
if let Err(e) = run_travel(args) {
if e.to_string().contains("exactly one time-travel destination") {
eprintln!("usage: tix travel <oid|^|~|first|tip>");
}
} Prevention
- Quote shell variables to avoid word-splitting into multiple args
- Default empty destination variables to an explicit value like HEAD
- Use a wrapper that enforces one positional argument
When it happens
Trigger: Invoking `tix travel` with no `to` target, or with more than one destination such that the argument match falls through to the `_` arm in run().
Common situations: Copy-pasting multiple OIDs; script variable expanding empty or containing spaces producing two args; forgetting the destination entirely.
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
- specify at least one contact to run through the mailmap
- detached HEAD or one of its descendants must be pinned…
- {notice}
- time-travel would conflict; retry with…
- HEAD is not present in the default Tix view
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/a25b7e50e9c57ac5.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/command/travel.rs:67
pub(super) fn run(repository: gix::Repository, args: Args) -> Result<()> {
let head = repository.head().context("could not read HEAD before time-travel")?;
let head_id = head
.id()
.map(gix::Id::detach)
.context("cannot time-travel from an unborn HEAD")?;
let detached = head.is_detached();
drop(head);
let (selected, resolved_graph) = match (&args.revision, args.to) {
(Some(revision), None) => super::resolve_commit(&repository, revision, "time-travel destination")?,
(None, Some(to)) => {
let hidden = crate::history::available_hidden_revisions(&repository, &[], true)?.0;
let hidden_tips = crate::history::snapshot(&repository, &[], &hidden, false)?.hidden_tips;
let graph = crate::edit::loaded_view_graph_with_hidden(&repository, &[], &hidden)?;
let selected = relative_destination(&repository, &graph, &hidden_tips, head_id, to)?;
(selected, Some(graph))
}
_ => anyhow::bail!("exactly one time-travel destination is required"),
};
if selected == head_id {
println!("already at {}", crate::change_id::display(&repository, selected, 7)?);
return Ok(());
}
let revisions = vec![OsString::from("HEAD"), OsString::from(selected.to_string())];
let graph = match resolved_graph {
Some(graph) => graph,
None => crate::edit::loaded_view_graph_with(&repository, &revisions)?,
};
let forward = graph.is_ancestor(head_id, selected);
if detached && !forward {
let source_is_pinned = crate::history::all_pins(&repository)?
.into_iter()
.any(|pin| graph.is_ancestor(head_id, pin.id));
if !source_is_pinned {
anyhow::bail!(View on GitHub (pinned to e73179060b)