GitoxideLabs/gitoxide · info

Cancelled by user

Error message

Cancelled by user

What it means

The query engine `update` function checks gix's global interrupt flag (set by Ctrl-C / SIGINT handlers) after joining each statistics thread and aborts with this message. It is a deliberate, cooperative cancellation - the work was stopped by the user, not by a data or logic failure.

Solutions

  1. Simply re-run the command without interrupting it; partial work is safe but must be redone
  2. Increase the timeout or resource budget of the surrounding CI/script so the command is not killed
  3. If cancellation must be handled, catch the error and treat it as an expected abort, not a bug
  4. Run the update incrementally on smaller commit ranges so each run finishes before interruption

Example fix

// before
handle.join().expect("no panic")?;
if gix::interrupt::is_triggered() {
    bail!("Cancelled by user");
}
// after
let join_result = handle.join().expect("no panic");
if gix::interrupt::is_triggered() {
    eprintln!("update cancelled by user; rerun to continue");
    std::process::exit(130);
}
join_result?;
Defensive patterns

Strategy: try-catch

Try / catch

match update(...) {
    Err(e) if e.to_string().contains("Cancelled by user") => {
        // expected: SIGINT; exit with conventional code 130
        std::process::exit(130);
    }
    other => other?,
}

Prevention

When it happens

Trigger: Pressing Ctrl-C (or programmatically triggering `gix::interrupt::trigger()`) while the public `update` function is joining stat_threads after computing commit statistics.

Common situations: User interrupts a long-running `gix query update` on a large repository; CI job timeouts sending SIGTERM/SIGINT to the process; automated scripts killing the command.

Related errors


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

Appendix: source

Thrown at gitoxide-core/src/query/engine/update.rs:464

                    break;
                }
                Err(err) => return Err(err.into()),
            }
        }
        db.send_last_chunk();
        let saw_new_commits = !commits.is_empty();
        if saw_new_commits {
            traverse_progress.show_throughput(start);
        }
        drop(traverse_progress);

        let stat_max = Some(commits.len());
        stat_progress.set_max(stat_max);
        db_progress.set_max(stat_max);
        for handle in stat_threads {
            handle.join().expect("no panic")?;
            if gix::interrupt::is_triggered() {
                bail!("Cancelled by user");
            }
        }
        if saw_new_commits {
            stat_progress.show_throughput(start);
            change_progress.show_throughput(start);
            lines_progress.show_throughput(start);
        }

        db_thread.join().expect("no panic")?;
        if saw_new_commits {
            db_progress.show_throughput(start);
        } else {
            db_progress.info("up to date".into());
        }

        commits.extend(all_commits);
        Ok(commits)
    })?;

View on GitHub (pinned to e73179060b)