{"record":{"id":"688533649e26f573","repo":"gitbutlerapp/gitbutler","slug":"editorexitedwithnonzerostatus","errorCode":"EditorExitedWithNonZeroStatus","errorMessage":"Editor exited with non-zero status","messagePattern":"Editor exited with non-zero status","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but/src/tui/get_text.rs","lineNumber":120,"sourceCode":"        if !initial_text.ends_with('\\n') {\n            writeln!(&mut tempfile)?;\n        }\n        writeln!(&mut tempfile, \"{REST_TEXT_MARKER}\")?;\n        writeln!(&mut tempfile, \"{rest_text}\")?;\n    }\n\n    // The editor command is allowed to be a shell expression, e.g. \"code --wait\" is somewhat common.\n    // We need to execute within a shell to make sure we don't get \"No such file or directory\" errors.\n    let status = gix::command::prepare(editor_cmd)\n        .arg(tempfile.path())\n        .stdin(std::process::Stdio::inherit())\n        .stdout(std::process::Stdio::inherit())\n        .with_shell()\n        .spawn()?\n        .wait()?;\n\n    if !status.success() {\n        return Err(anyhow::anyhow!(\"Editor exited with non-zero status\")\n            .context(Code::EditorExitedWithNonZeroStatus));\n    }\n\n    Ok(std::fs::read(&tempfile)\n        .context(\"failed to read contents of commit message file\")?\n        .into())\n}\n\n/// Launch the built-in TUI editor.\nfn from_builtin_editor(\n    filename_safe_intent: &str,\n    initial_text: &str,\n    rest_text: Option<&str>,\n) -> Result<BString> {\n    // Determine editor mode based on the intent\n    let mode = if filename_safe_intent.contains(\"commit\") {\n        super::editor::EditorMode::CommitMessage\n    } else if filename_safe_intent.contains(\"branch\") {","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/tui/get_text.rs#L102-L138","documentation":"When but needs text (e.g. a commit message) it spawns the configured editor through a shell (so commands like 'code --wait' work) and waits for it. If the editor process exits non-zero, the operation aborts with Code::EditorExitedWithNonZeroStatus attached as context. Quitting vim with :cq is the idiomatic deliberate way to trigger this.","triggerScenarios":"Quitting the editor with :cq to abort; the editor binary missing so the shell exits 127; GUI editors returning instantly because a blocking flag like --wait is absent; the editor crashing or being killed.","commonSituations":"Intentional aborts via :cq; core.editor/GIT_EDITOR misconfigured; VS Code without --wait; editor not on PATH in the environment but inherited.","solutions":["If you aborted on purpose with :cq, rerun the command and save the message normally","Test the editor standalone ($EDITOR /tmp/t) and fix core.editor if it fails or returns instantly, e.g. `git config --global core.editor 'code --wait'`","Interpret the status: 127 means the shell could not find the editor command","Provide the message non-interactively (e.g. -m flag) so no editor is launched"],"exampleFix":"# before\ngit config --global core.editor \"code\"     # returns instantly -> failure\n# after\ngit config --global core.editor \"code --wait\"","handlingStrategy":"try-catch","validationCode":"use which::which;\n\nlet prog = editor_cmd.split_whitespace().next().unwrap_or_default();\nif which(prog).is_err() {\n    return Err(anyhow!(\"editor '{prog}' not found on PATH\"));\n}","typeGuard":null,"tryCatchPattern":"Inspect the error chain for Code::EditorExitedWithNonZeroStatus and branch: treat it as a user abort (drop the operation quietly) versus a real editor failure (surface the editor command and exit status).","preventionTips":["Configure blocking editors ('code --wait', 'vim') in core.editor","Verify $EDITOR works from a terminal before scripting commits","Offer non-interactive message input (-m) in automation"],"tags":["editor","commit-message","process","exit-code","git-config"],"backgroundTag":"editor-exit-non-zero","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}