GitoxideLabs/gitoxide · warning
interrupted by user
Error message
interrupted by user
What it means
During `perform_run`, before each repository in the corpus is processed the engine checks `gix::interrupt::is_triggered()` (SIGINT/Ctrl-C flag). If an interrupt signal was received, it aborts the whole run with this bail so the process exits with a clear error instead of being killed mid-write.
Solutions
- This is expected on user interruption — no fix needed; re-run the command without sending a signal.
- If interruption happens unintentionally, check terminal/CI signal forwarding (e.g. CI cancellation, `timeout` commands).
- For long runs, restrict the corpus with a repo SQL suffix or fewer tasks so runs finish before you need to interrupt.
- Handle the resulting `anyhow` error gracefully in scripts by checking for the 'interrupted by user' message.
Defensive patterns
Strategy: try-catch
Try / catch
match res {
Err(e) if e.to_string() == "interrupted by user" => {
eprintln!("run cancelled; partial results kept");
}
other => other?,
} Prevention
- Don't send SIGINT unless you intend to abort the corpus run.
- Check CI cancellation semantics if runs are aborted unexpectedly.
- Plan long runs with a repo SQL suffix or task filter to shorten duration.
- Persist progress so interrupted runs can resume cheaply.
When it happens
Trigger: Pressing Ctrl-C (or sending SIGINT) to the process while `Engine::perform_run` is iterating over corpus repositories, causing the `gix::interrupt` handler flag to be set before the next repo begins.
Common situations: A developer realizes a corpus run over hundreds of repos is taking too long and hits Ctrl-C; a CI job is cancelled and the harness sends SIGINT; a user interrupts after seeing bad progress output.
Related errors
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/385e1ac4d9a08e83.
Report an issue: GitHub.
Appendix: source
Thrown at gitoxide-core/src/corpus/engine.rs:118
repo_progress.inc();
}
repo_progress.info(format!("with {} tasks", tasks.len()));
for (_, task) in tasks {
repo_progress.info(format!("task '{}' ({})", task.description, task.short_name));
}
break 'tasks_loop;
}
let mut run_progress = repo_progress.add_child("set later");
let (_guard, current_id) = corpus::trace::override_thread_subscriber(
db_path.as_str(),
self.state.trace_to_progress.then(|| repo_progress.add_child("trace")),
self.state.reverse_trace_lines,
)?;
let mut num_errors = 0;
for repo in &repos {
if gix::interrupt::is_triggered() {
bail!("interrupted by user");
}
run_progress.set_name(format!(
"{}",
repo.path
.strip_prefix(corpus_path)
.expect("corpus contains repo")
.display()
));
// TODO: wait for new release of `tracing-forest` to be able to provide run_id via span attributes
let mut run = Self::insert_run(&self.con, gitoxide_id, runner_id, *task_id, repo.id)?;
current_id.store(run.id, Ordering::SeqCst);
tracing::info_span!("run", run_id = run.id).in_scope(|| {
task.perform(
&mut run,
&repo.path,
&mut run_progress,
Some(threads),View on GitHub (pinned to e73179060b)