sigoden/aichat · info · anyhow::Error

Aborted!

Error message

Aborted!

What it means

abortable_run_with_spinner_rx races the user's task against Ctrl+C (tokio::signal::ctrl_c). When the user presses Ctrl+C, the function sets the abort signal, notifies the spinner, and bails with 'Aborted!'. It signals intentional user-interrupted cancellation rather than an unexpected failure.

Solutions

  1. Re-run the command and let it finish without pressing Ctrl+C
  2. Check for network/API slowness that tempts cancellation (timeouts, connectivity)
  3. Handle the aborted result gracefully in scripts and re-invoke when needed
  4. Reduce workload size (fewer documents, smaller batches) so runs complete quickly
Defensive patterns

Strategy: try-catch

Try / catch

match abortable_run_with_spinner_rx(task, spinner, signal).await {
    Err(e) if e.to_string() == "Aborted!" => {
        eprintln!("operation cancelled by user (Ctrl+C)");
        std::process::exit(130); // conventional SIGINT exit code
    }
    other => other?,
}

Prevention

When it happens

Trigger: Pressing Ctrl+C while a task wrapped in the abortable spinner is running (e.g. during init or refresh_document_paths long-running operations).

Common situations: User cancels a long network request, model stream, or document refresh; impatient re-press of Ctrl+C during any spinner-wrapped command.

Related errors


AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/b6f03872ac797b1c. Report an issue: GitHub.

Appendix: source

Thrown at src/utils/spinner.rs:159

    task: F,
    spinner_rx: UnboundedReceiver<SpinnerEvent>,
    abort_signal: AbortSignal,
) -> Result<T>
where
    F: Future<Output = Result<T>>,
{
    if *IS_STDOUT_TERMINAL {
        let (done_tx, done_rx) = oneshot::channel();
        let run_task = async {
            tokio::select! {
                ret = task => {
                    let _ = done_tx.send(());
                    ret
                }
                _ = tokio::signal::ctrl_c() => {
                    abort_signal.set_ctrlc();
                    let _ = done_tx.send(());
                    bail!("Aborted!")
                },
                _ = wait_abort_signal(&abort_signal) => {
                    let _ = done_tx.send(());
                    bail!("Aborted.");
                },
            }
        };
        let (task_ret, spinner_ret) = tokio::join!(
            run_task,
            run_abortable_spinner(spinner_rx, done_rx, abort_signal.clone())
        );
        spinner_ret?;
        task_ret
    } else {
        task.await
    }
}

View on GitHub (pinned to 82976d349a)