GitoxideLabs/gitoxide · info · anyhow::Error

interrupted by user

Error message

interrupted by user

What it means

During commit traversal, `list` polls `gix::interrupt::is_triggered()` each iteration and bails with 'interrupted by user' when an interrupt signal (SIGINT/Ctrl-C) was received. This converts the interrupt flag into a normal error return so the command unwinds cleanly, flushing progress state instead of aborting the process abruptly.

Solutions

  1. Nothing to fix — this is expected behavior on user interruption; simply re-run the command if needed
  2. Avoid sending SIGINT until traversal completes, or run to completion in background with nohup
  3. Use `--limit` to bound traversal size so it finishes quickly
  4. Handle the interrupt error in scripts by checking exit status for cancellation
Defensive patterns

Strategy: try-catch

Try / catch

# shell: treat non-zero with 'interrupted by user' as cancellation, not failure
gix revision list "$spec" ||
  case $? in
    130|1) grep -q 'interrupted by user' err.log && exit 130 ;;
  esac

Prevention

When it happens

Trigger: Pressing Ctrl-C (or sending SIGINT, or anything setting gix's interrupt flag, e.g. another thread calling `gix::interrupt::trigger()`) while `gix revision list` is traversing commits.

Common situations: Users cancelling a long-running traversal of large repositories; CI systems terminating jobs with SIGINT; watchdogs interrupting slow commands.

Related errors


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

Appendix: source

Thrown at gitoxide-core/src/repository/revision/list.rs:77

            .sorting(Sorting::ByCommitTime(Default::default()))
            .all()?;

        let mut vg = match text {
            Format::Svg { path } => (
                layout::topo::layout::VisualGraph::new(Orientation::TopToBottom),
                path,
                HashMap::default(),
            )
                .into(),
            Format::Text => None,
        };
        progress.init(None, gix::progress::count("commits"));
        progress.set_name("traverse".into());

        let start = std::time::Instant::now();
        for commit in commits {
            if gix::interrupt::is_triggered() {
                bail!("interrupted by user");
            }
            let commit = commit?;
            match vg.as_mut() {
                Some((vg, _path, map)) => {
                    let source = match map.get(&commit.id) {
                        Some(handle) => *handle,
                        None => {
                            let handle = vg.add_node(new_node(commit.id()));
                            map.insert(commit.id, handle);
                            handle
                        }
                    };

                    for parent_id in commit.parent_ids() {
                        let dest = match map.get(parent_id.as_ref()) {
                            Some(handle) => *handle,
                            None => {
                                let dest = vg.add_node(new_node(parent_id));

View on GitHub (pinned to e73179060b)