{"record":{"id":"c8ee563d2bbd66be","repo":"GitoxideLabs/gitoxide","slug":"interrupted-by-user-c8ee56","errorCode":null,"errorMessage":"interrupted by user","messagePattern":"interrupted by user","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"info","filePath":"gitoxide-core/src/repository/revision/list.rs","lineNumber":77,"sourceCode":"            .sorting(Sorting::ByCommitTime(Default::default()))\n            .all()?;\n\n        let mut vg = match text {\n            Format::Svg { path } => (\n                layout::topo::layout::VisualGraph::new(Orientation::TopToBottom),\n                path,\n                HashMap::default(),\n            )\n                .into(),\n            Format::Text => None,\n        };\n        progress.init(None, gix::progress::count(\"commits\"));\n        progress.set_name(\"traverse\".into());\n\n        let start = std::time::Instant::now();\n        for commit in commits {\n            if gix::interrupt::is_triggered() {\n                bail!(\"interrupted by user\");\n            }\n            let commit = commit?;\n            match vg.as_mut() {\n                Some((vg, _path, map)) => {\n                    let source = match map.get(&commit.id) {\n                        Some(handle) => *handle,\n                        None => {\n                            let handle = vg.add_node(new_node(commit.id()));\n                            map.insert(commit.id, handle);\n                            handle\n                        }\n                    };\n\n                    for parent_id in commit.parent_ids() {\n                        let dest = match map.get(parent_id.as_ref()) {\n                            Some(handle) => *handle,\n                            None => {\n                                let dest = vg.add_node(new_node(parent_id));","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gitoxide-core/src/repository/revision/list.rs#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"Users cancelling a long-running traversal of large repositories; CI systems terminating jobs with SIGINT; watchdogs interrupting slow commands.","solutions":["Nothing to fix — this is expected behavior on user interruption; simply re-run the command if needed","Avoid sending SIGINT until traversal completes, or run to completion in background with nohup","Use `--limit` to bound traversal size so it finishes quickly","Handle the interrupt error in scripts by checking exit status for cancellation"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"# shell: treat non-zero with 'interrupted by user' as cancellation, not failure\ngix revision list \"$spec\" ||\n  case $? in\n    130|1) grep -q 'interrupted by user' err.log && exit 130 ;;\n  esac","preventionTips":["Don't send SIGINT to long traversals; use --limit to keep runs short","Run long jobs under nohup/setsid detached from terminal signals","In Rust, check gix::interrupt::is_triggered() in your own loops for graceful shutdown","Distinguish interrupt exit codes from real errors in CI retry logic"],"tags":["cli","interrupt","signal","traversal"],"backgroundTag":"operation-interrupted-by-user","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}