{"record":{"id":"d77e49925beca41b","repo":"GitoxideLabs/gitoxide","slug":"cancelled-by-user-d77e49","errorCode":null,"errorMessage":"Cancelled by user","messagePattern":"Cancelled by user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"gitoxide-core/src/query/engine/update.rs","lineNumber":464,"sourceCode":"                    break;\n                }\n                Err(err) => return Err(err.into()),\n            }\n        }\n        db.send_last_chunk();\n        let saw_new_commits = !commits.is_empty();\n        if saw_new_commits {\n            traverse_progress.show_throughput(start);\n        }\n        drop(traverse_progress);\n\n        let stat_max = Some(commits.len());\n        stat_progress.set_max(stat_max);\n        db_progress.set_max(stat_max);\n        for handle in stat_threads {\n            handle.join().expect(\"no panic\")?;\n            if gix::interrupt::is_triggered() {\n                bail!(\"Cancelled by user\");\n            }\n        }\n        if saw_new_commits {\n            stat_progress.show_throughput(start);\n            change_progress.show_throughput(start);\n            lines_progress.show_throughput(start);\n        }\n\n        db_thread.join().expect(\"no panic\")?;\n        if saw_new_commits {\n            db_progress.show_throughput(start);\n        } else {\n            db_progress.info(\"up to date\".into());\n        }\n\n        commits.extend(all_commits);\n        Ok(commits)\n    })?;","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gitoxide-core/src/query/engine/update.rs#L446-L482","documentation":"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.","triggerScenarios":"Pressing Ctrl-C (or programmatically triggering `gix::interrupt::trigger()`) while the public `update` function is joining stat_threads after computing commit statistics.","commonSituations":"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.","solutions":["Simply re-run the command without interrupting it; partial work is safe but must be redone","Increase the timeout or resource budget of the surrounding CI/script so the command is not killed","If cancellation must be handled, catch the error and treat it as an expected abort, not a bug","Run the update incrementally on smaller commit ranges so each run finishes before interruption"],"exampleFix":"// before\nhandle.join().expect(\"no panic\")?;\nif gix::interrupt::is_triggered() {\n    bail!(\"Cancelled by user\");\n}\n// after\nlet join_result = handle.join().expect(\"no panic\");\nif gix::interrupt::is_triggered() {\n    eprintln!(\"update cancelled by user; rerun to continue\");\n    std::process::exit(130);\n}\njoin_result?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match update(...) {\n    Err(e) if e.to_string().contains(\"Cancelled by user\") => {\n        // expected: SIGINT; exit with conventional code 130\n        std::process::exit(130);\n    }\n    other => other?,\n}","preventionTips":["Avoid sending SIGINT/SIGTERM to long-running update commands; use checkpoints instead","Configure generous CI timeouts for large-repository updates","Split updates into smaller incremental runs so each finishes quickly"],"tags":["interrupt","user-cancellation","signal"],"backgroundTag":"operation-cancelled","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}