{"record":{"id":"33dce350cef26cde","repo":"pbakaus/impeccable","slug":"update-failed-aborted","errorCode":null,"errorMessage":"Update failed: Aborted.","messagePattern":"Update failed: Aborted\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/skills/src/commands.rs","lineNumber":848,"sourceCode":"        util::rm_rf(&tmp_dir);\n        return match outcome {\n            Ok(hook_targets) => {\n                let v = sys.get_skills_version(&root, scope);\n                out(io, &format!(\"Skills are up to date{}.\", version_suffix(&v)));\n                if !hook_targets.is_empty() {\n                    out(io, &format!(\"Installed hooks into: {}\", hook_targets.join(\", \")));\n                }\n                out(io, \"Nothing else to do.\");\n                Err(Flow::Exit(0))\n            }\n            Err(Flow::Throw(e)) => {\n                err(io, &format!(\"Update failed: {e}\"));\n                Err(Flow::Exit(1))\n            }\n            // JS: the try/catch around decideHookInstall swallows the prompt\n            // abort too, printing its message.\n            Err(Flow::Abort) => {\n                err(io, \"Update failed: Aborted.\");\n                Err(Flow::Exit(1))\n            }\n            Err(other) => Err(other),\n        };\n    }\n\n    out(io, &format!(\"Found skills in: {}\", copy_providers.join(\", \")));\n\n    if !yes {\n        let ans = prompt.ask(io, &format!(\"Update skills in {} provider folder(s)? (Y/n) \", copy_providers.len()))?;\n        if ans == \"n\" || ans == \"no\" {\n            util::rm_rf(&tmp_dir);\n            out(io, \"Aborted.\");\n            return Err(Flow::Exit(0));\n        }\n    }\n\n    let outcome: R<()> = (|| {","sourceCodeStart":830,"sourceCodeEnd":866,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/crates/skills/src/commands.rs#L830-L866","documentation":"If the user aborts the hook-installation prompt during `update` (e.g. answering 'no'/cancelling at decide_hook_install), the abort is surfaced as 'Update failed: Aborted.' with exit code 1. A comment notes the JS version's try/catch swallowed the prompt abort and printed its own message instead.","triggerScenarios":"`update` when the interactive hook-install prompt is declined or cancelled by the user, producing Flow::Abort; happens only when hooks are being considered (no --no-hooks) and the prompt runs without --yes.","commonSituations":"Users cancelling the prompt in CI (no TTY) or accidentally; scripted runs where stdin is closed so the prompt aborts; users who do not want hooks but ran update without --no-hooks.","solutions":["Pass --no-hooks to skip hook installation and its prompt entirely.","Pass --yes to auto-accept prompts in scripts/CI.","Provide a TTY/stdin when running update non-interactively."],"exampleFix":"// before (CI, no TTY)\nimpeccable update  # Update failed: Aborted.\n// after\nimpeccable update --no-hooks --yes","handlingStrategy":"fallback","validationCode":"[ -t 0 ] || { echo \"non-interactive shell: use --yes/--no-hooks\"; }","typeGuard":null,"tryCatchPattern":"impeccable update --no-hooks || impeccable update --no-hooks --yes","preventionTips":["Always pass --yes (and/or --no-hooks) in scripts and CI.","Only run interactive updates in a TTY session.","Decide your hooks policy once and encode it in your update script."],"tags":["update","aborted","prompt","cli","non-interactive"],"backgroundTag":"operation-aborted","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}