{"record":{"id":"b6f03872ac797b1c","repo":"sigoden/aichat","slug":"aborted-b6f038","errorCode":null,"errorMessage":"Aborted!","messagePattern":"Aborted!","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"info","filePath":"src/utils/spinner.rs","lineNumber":159,"sourceCode":"    task: F,\n    spinner_rx: UnboundedReceiver<SpinnerEvent>,\n    abort_signal: AbortSignal,\n) -> Result<T>\nwhere\n    F: Future<Output = Result<T>>,\n{\n    if *IS_STDOUT_TERMINAL {\n        let (done_tx, done_rx) = oneshot::channel();\n        let run_task = async {\n            tokio::select! {\n                ret = task => {\n                    let _ = done_tx.send(());\n                    ret\n                }\n                _ = tokio::signal::ctrl_c() => {\n                    abort_signal.set_ctrlc();\n                    let _ = done_tx.send(());\n                    bail!(\"Aborted!\")\n                },\n                _ = wait_abort_signal(&abort_signal) => {\n                    let _ = done_tx.send(());\n                    bail!(\"Aborted.\");\n                },\n            }\n        };\n        let (task_ret, spinner_ret) = tokio::join!(\n            run_task,\n            run_abortable_spinner(spinner_rx, done_rx, abort_signal.clone())\n        );\n        spinner_ret?;\n        task_ret\n    } else {\n        task.await\n    }\n}\n","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/utils/spinner.rs#L141-L177","documentation":"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.","triggerScenarios":"Pressing Ctrl+C while a task wrapped in the abortable spinner is running (e.g. during init or refresh_document_paths long-running operations).","commonSituations":"User cancels a long network request, model stream, or document refresh; impatient re-press of Ctrl+C during any spinner-wrapped command.","solutions":["Re-run the command and let it finish without pressing Ctrl+C","Check for network/API slowness that tempts cancellation (timeouts, connectivity)","Handle the aborted result gracefully in scripts and re-invoke when needed","Reduce workload size (fewer documents, smaller batches) so runs complete quickly"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match abortable_run_with_spinner_rx(task, spinner, signal).await {\n    Err(e) if e.to_string() == \"Aborted!\" => {\n        eprintln!(\"operation cancelled by user (Ctrl+C)\");\n        std::process::exit(130); // conventional SIGINT exit code\n    }\n    other => other?,\n}","preventionTips":["Avoid pressing Ctrl+C mid-run; prefer commands that checkpoint/resume","Use timeouts/retries for flaky network operations instead of manual cancels","In scripts, treat 'Aborted!' as exit code 130 and re-run idempotent steps"],"tags":["cancellation","ctrl-c","spinner","user-interrupt"],"backgroundTag":"user-interrupt-abort","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}