{"record":{"id":"16715ce2a020625f","repo":"can1357/oh-my-pi","slug":"operation-canceled","errorCode":null,"errorMessage":"operation canceled","messagePattern":"operation canceled","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"info","filePath":"crates/pi-vcs/src/error.rs","lineNumber":97,"sourceCode":"\t\t/// Rendered command line.\n\t\tcommand: String,\n\t},\n\n\t/// Filesystem error outside any more specific failure mode.\n\t#[error(transparent)]\n\tIo(#[from] std::io::Error),\n\n\t/// An underlying gix / jj-lib failure that has no dedicated variant.\n\t#[error(\"{context}: {message}\")]\n\tBackend {\n\t\t/// Operation being performed (`\"git status\"`, `\"jj snapshot\"`, …).\n\t\tcontext: &'static str,\n\t\t/// Backend error rendered as text (full source chain).\n\t\tmessage: String,\n\t},\n\n\t/// The operation was canceled via its interrupt flag.\n\t#[error(\"operation canceled\")]\n\tCanceled,\n\t/// The operation has no implementation on this backend (e.g. staged diffs\n\t/// on a Jujutsu workspace, which has no index).\n\t#[error(\n\t\t\"`{operation}` is not supported on a {} repository\",\n\t\tmatch backend {\n\t\t\tcrate::VcsKind::Git => \"git\",\n\t\t\tcrate::VcsKind::Jj => \"jj\",\n\t\t}\n\t)]\n\tUnsupported {\n\t\t/// Operation or feature name as exposed to JS (camelCase).\n\t\toperation: &'static str,\n\t\t/// Backend that lacks it.\n\t\tbackend:   crate::VcsKind,\n\t},\n}\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-vcs/src/error.rs#L79-L115","documentation":"Error::Canceled indicates the operation was aborted via its interrupt/cancellation flag before completing. This is an expected control-flow signal, not a malfunction: a caller (or embedding UI) asked the library to stop, and the library unwound with this sentinel.","triggerScenarios":"Setting the operation's interrupt flag during a long-running scan/status/log while it is in flight: user pressing Escape in a TUI, request cancellation in an RPC handler, or a supervisor cancelling a batch of VCS operations partway through.","commonSituations":"Users cancelling a slow `git log`/status search in an editor plugin, timeout controllers that flip the interrupt flag, or app shutdown racing an in-progress VCS read.","solutions":["Treat this variant as benign: catch it and clean up without reporting an error to the user.","If cancellation was unintended, audit where the interrupt flag is set (shared flag, stale UI state) and reset it before starting new operations.","Retrigger the operation with a fresh, unset interrupt flag.","In batch pipelines, decide per-batch whether to continue remaining items or abort the whole batch on cancel."],"exampleFix":"// before\nlet result = op.run()?; // Canceled bubbles up as an error toast\n// after\nmatch op.run() {\n    Err(Error::Canceled) => Ok(None), // user aborted — not an error\n    other => other.map(Some),\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_canceled(err: &pi_vcs::Error) -> bool {\n    matches!(err, pi_vcs::Error::Canceled)\n}","tryCatchPattern":"match operation.run(interrupt_flag) {\n    Err(pi_vcs::Error::Canceled) => {\n        // user-initiated abort: report nothing, clean up quietly\n        cleanup_partial_state();\n    }\n    other => other?,\n}","preventionTips":["Reset the interrupt flag before starting each new operation.","Route all user-cancel actions through the flag, and handle the Canceled variant explicitly everywhere you run operations.","Distinguish Canceled from real errors in error-reporting UI so aborts never show as failures.","Avoid sharing one interrupt flag across unrelated concurrent operations."],"tags":["vcs","cancellation","control-flow","async"],"backgroundTag":"operation-canceled","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}