GitoxideLabs/gitoxide · warning
Cancelled by user
Error message
Cancelled by user
What it means
In the `hours` command's `estimate`, while walking a commit's ancestors the inner loop checks `gix::interrupt::is_triggered()` after each iteration and bails with this message so a long-running history walk can be cancelled cleanly by SIGINT/Ctrl-C.
Solutions
- Expected on interruption — simply re-run `gix hours` when ready.
- Narrow the analysis (smaller repo range, fewer repos) so runs complete faster.
- Avoid sending SIGINT during the walk; use progress output to gauge remaining time.
- In scripts, treat this error as a cancellation status rather than a bug.
Defensive patterns
Strategy: try-catch
Try / catch
match res {
Err(e) if e.to_string() == "Cancelled by user" => {
eprintln!("hours estimate cancelled by SIGINT");
}
other => other?,
} Prevention
- Run `gix hours` in a terminal you won't need to interrupt; estimate duration from progress output first.
- For very large repositories, sample fewer commits or repos.
- In CI, disable automatic cancellation signals for this step or catch them.
When it happens
Trigger: Sending SIGINT (Ctrl-C) while `estimate` is traversing commit ancestors via `commit_id.ancestors(&repo.objects)`; the check fires at the top of the next `while let Some(c) = commit_iter.next()` iteration.
Common situations: A developer running `gix hours` on a huge repository (tens of thousands of commits) decides to cancel it; a CI pipeline cancellation sends SIGINT mid-walk.
Related errors
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/26ec05252f9071d5.
Report an issue: GitHub.
Appendix: source
Thrown at gitoxide-core/src/hours/mod.rs:227
repo.clone(),
stats_counters.clone().expect("counters are set"),
);
(Some(tx), threads)
}
} else {
Default::default()
};
let mut commit_idx = 0_u32;
let mut skipped_merge_commits = 0;
const CHUNK_SIZE: usize = 50;
let mut chunk = Vec::with_capacity(CHUNK_SIZE);
let mut commit_iter = commit_id.ancestors(&repo.objects);
let mut is_shallow = false;
while let Some(c) = commit_iter.next() {
progress.inc();
if gix::interrupt::is_triggered() {
bail!("Cancelled by user");
}
match c {
Ok(c) => {
tx.send((commit_idx, commit_iter.commit_data().to_owned())).ok();
let tree_delta_info = tx_tree_id.as_ref().and_then(|tx| {
let mut parents = c.parent_ids.into_iter();
parents
.next()
.map(|first_parent| (tx, Some(first_parent), c.id.to_owned()))
.filter(|_| {
if parents.next().is_some() {
skipped_merge_commits += 1;
false
} else {
true
}
})
});View on GitHub (pinned to e73179060b)